﻿(function()
{
    var e, t = this,
        n = t.Backbone,
        i = [],
        o = i.push,
        s = i.slice,
        r = i.splice;
    e = "undefined" !== typeof exports ? exports : t.Backbone = {},
    e.VERSION = "0.9.10";
    var a = t._;
    a || "undefined" === typeof require || (a = require("underscore")),
    e.$ = t.jQuery || t.Zepto || t.ender,
    e.noConflict = function()
    {
        return t.Backbone = n,
        this;
    },
    e.emulateHTTP = !1,
    e.emulateJSON = !1;
    var l = /\s+/,
        u = function(e, t, n, i)
        {
            if (!n)
            {
                return !0;
            }
            if ("object" === typeof n)
            {
                for (var o in n)
                {
                    e[t].apply(e, [o, n[o]].concat(i));
                }
            }
            else
            {
                if (!l.test(n))
                {
                    return !0;
                }
                for (var s = n.split(l), r = 0, a = s.length; r < a; r++)
                {
                    e[t].apply(e, [s[r]].concat(i));
                }
            }
        },
        c = function(e, t)
        {
            var n, i = -1,
                o = e.length;
            switch (t.length)
            {
                case 0:
                    for (; ++i < o;)
                    {
                        (n = e[i]).callback.call(n.ctx);
                    }
                    return;
                case 1:
                    for (; ++i < o;)
                    {
                        (n = e[i]).callback.call(n.ctx, t[0]);
                    }
                    return;
                case 2:
                    for (; ++i < o;)
                    {
                        (n = e[i]).callback.call(n.ctx, t[0], t[1]);
                    }
                    return;
                case 3:
                    for (; ++i < o;)
                    {
                        (n = e[i]).callback.call(n.ctx, t[0], t[1], t[2]);
                    }
                    return;
                default:
                    for (; ++i < o;)
                    {
                        (n = e[i]).callback.apply(n.ctx, t);
                    }
            }
        },
        d = e.Events = {
            on: function(e, t, n)
            {
                if (!u(this, "on", e, [t, n]) || !t)
                {
                    return this;
                }
                this._events || (this._events = {});
                var i = this._events[e] || (this._events[e] = []);
                return i.push({
                    callback: t,
                    context: n,
                    ctx: n || this
                }),
                this;
            },
            once: function(e, t, n)
            {
                if (!u(this, "once", e, [t, n]) || !t)
                {
                    return this;
                }
                var i = this,
                    o = a.once(function()
                    {
                        i.off(e, o),
                        t.apply(this, arguments);
                    });
                return o._callback = t,
                this.on(e, o, n),
                this;
            },
            off: function(e, t, n)
            {
                var i, o, s, r, l, c, d, h;
                if (!this._events || !u(this, "off", e, [t, n]))
                {
                    return this;
                }
                if (!e && !t && !n)
                {
                    return this._events = {},
                    this;
                }
                for (r = e ? [e] : a.keys(this._events), l = 0, c = r.length; l < c; l++)
                {
                    if (e = r[l], i = this._events[e])
                    {
                        if (s = [], t || n)
                        {
                            for (d = 0, h = i.length; d < h; d++)
                            {
                                o = i[d],
                                (t && t !== o.callback && t !== o.callback._callback || n && n !== o.context) && s.push(o);
                            }
                        }
                        this._events[e] = s;
                    }
                }
                return this;
            },
            trigger: function(e)
            {
                if (!this._events)
                {
                    return this;
                }
                var t = s.call(arguments, 1);
                if (!u(this, "trigger", e, t))
                {
                    return this;
                }
                var n = this._events[e],
                    i = this._events.all;
                return n && c(n, t),
                i && c(i, arguments),
                this;
            },
            listenTo: function(e, t, n)
            {
                var i = this._listeners || (this._listeners = {}),
                    o = e._listenerId || (e._listenerId = a.uniqueId("l"));
                return i[o] = e,
                e.on(t, "object" === typeof t ? this : n, this),
                this;
            },
            stopListening: function(e, t, n)
            {
                var i = this._listeners;
                if (i)
                {
                    if (e)
                    {
                        e.off(t, "object" === typeof t ? this : n, this),
                        t || n || delete i[e._listenerId];
                    }
                    else
                    {
                        "object" === typeof t && (n = this);
                        for (var o in i)
                        {
                            i[o].off(t, n, this);
                        }
                        this._listeners = {};
                    }
                    return this;
                }
            }
        };
    d.bind = d.on,
    d.unbind = d.off,
    a.extend(e, d);
    var h = e.Model = function(e, t)
    {
        var n, i = e || {};
        this.cid = a.uniqueId("c"),
        this.attributes = {},
        t && t.collection && (this.collection = t.collection),
        t && t.parse && (i = this.parse(i, t) || {}),
        (n = a.result(this, "defaults")) && (i = a.defaults({},
            i, n)),
        this.set(i, t),
        this.changed = {},
        this.initialize.apply(this, arguments);
    };
    a.extend(h.prototype, d, {
        changed: null,
        idAttribute: "id",
        initialize: function()
        {
        },
        toJSON: function()
        {
            return a.clone(this.attributes);
        },
        sync: function()
        {
            return e.sync.apply(this, arguments);
        },
        get: function(e)
        {
            return this.attributes[e];
        },
        escape: function(e)
        {
            return a.escape(this.get(e));
        },
        has: function(e)
        {
            return null != this.get(e);
        },
        set: function(e, t, n)
        {
            var i, o, s, r, l, u, c, d;
            if (null == e)
            {
                return this;
            }
            if ("object" === typeof e ? (o = e, n = t) : (o = {})[e] = t, n || (n = {}), !this._validate(o, n))
            {
                return !1;
            }
            s = n.unset,
            l = n.silent,
            r = [],
            u = this._changing,
            this._changing = !0,
            u || (this._previousAttributes = a.clone(this.attributes), this.changed = {}),
            d = this.attributes,
            c = this._previousAttributes,
            this.idAttribute in o && (this.id = o[this.idAttribute]);
            for (i in o)
            {
                t = o[i],
                a.isEqual(d[i], t) || r.push(i),
                a.isEqual(c[i], t) ? delete this.changed[i] : this.changed[i] = t,
                s ? delete d[i] : d[i] = t;
            }
            if (!l)
            {
                r.length && (this._pending = !0);
                for (var h = 0,
                    p = r.length; h < p; h++)
                {
                    this.trigger("change:" + r[h], this, d[r[h]], n);
                }
            }
            if (u)
            {
                return this;
            }
            if (!l)
            {
                for (; this._pending;)
                {
                    this._pending = !1,
                    this.trigger("change", this, n);
                }
            }
            return this._pending = !1,
            this._changing = !1,
            this;
        },
        unset: function(e, t)
        {
            return this.set(e, void 0, a.extend({},
                t, {
                    unset: !0
                }));
        },
        clear: function(e)
        {
            var t = {};
            for (var n in this.attributes)
            {
                t[n] = void 0;
            }
            return this.set(t, a.extend({},
                e, {
                    unset: !0
                }));
        },
        hasChanged: function(e)
        {
            return null == e ? !a.isEmpty(this.changed) : a.has(this.changed, e);
        },
        changedAttributes: function(e)
        {
            if (!e)
            {
                return this.hasChanged() ? a.clone(this.changed) : !1;
            }
            var t, n = !1,
                i = this._changing ? this._previousAttributes : this.attributes;
            for (var o in e)
            {
                a.isEqual(i[o], t = e[o]) || ((n || (n = {}))[o] = t);
            }
            return n;
        },
        previous: function(e)
        {
            return null != e && this._previousAttributes ? this._previousAttributes[e] : null;
        },
        previousAttributes: function()
        {
            return a.clone(this._previousAttributes);
        },
        fetch: function(e)
        {
            e = e ? a.clone(e) : {},
            void 0 === e.parse && (e.parse = !0);
            var t = e.success;
            return e.success = function(e, n, i)
            {
                return e.set(e.parse(n, i), i) ? (t && t(e, n, i), void 0) : !1;
            },
            this.sync("read", this, e);
        },
        save: function(e, t, n)
        {
            var i, o, s, r, l = this.attributes;
            return null == e || "object" === typeof e ? (i = e, n = t) : (i = {})[e] = t,
            !i || n && n.wait || this.set(i, n) ? (n = a.extend({
                validate: !0
            },
                    n), this._validate(i, n) ? (i && n.wait && (this.attributes = a.extend({},
                            l, i)), void 0 === n.parse && (n.parse = !0), o = n.success, n.success = function(e, t, n)
                            {
                                e.attributes = l;
                                var s = e.parse(t, n);
                                return n.wait && (s = a.extend(i || {},
                                    s)),
                                a.isObject(s) && !e.set(s, n) ? !1 : (o && o(e, t, n), void 0);
                            },
                    s = this.isNew() ? "create" : n.patch ? "patch" : "update", "patch" === s && (n.attrs = i), r = this.sync(s, this, n), i && n.wait && (this.attributes = l), r) : !1) : !1;
        },
        destroy: function(e)
        {
            e = e ? a.clone(e) : {};
            var t = this,
                n = e.success,
                i = function()
                {
                    t.trigger("destroy", t, t.collection, e);
                };
            if (e.success = function(e, t, o)
            {
                (o.wait || e.isNew()) && i(),
                n && n(e, t, o);
            },
            this.isNew())
            {
                return e.success(this, null, e),
                !1;
            }
            var o = this.sync("delete", this, e);
            return e.wait || i(),
            o;
        },
        url: function()
        {
            var e = a.result(this, "urlRoot") || a.result(this.collection, "url") || M();
            return this.isNew() ? e : e + ("/" === e.charAt(e.length - 1) ? "" : "/") + encodeURIComponent(this.id);
        },
        parse: function(e)
        {
            return e;
        },
        clone: function()
        {
            return new this.constructor(this.attributes);
        },
        isNew: function()
        {
            return null == this.id;
        },
        isValid: function(e)
        {
            return !this.validate || !this.validate(this.attributes, e);
        },
        _validate: function(e, t)
        {
            if (!t.validate || !this.validate)
            {
                return !0;
            }
            e = a.extend({},
                this.attributes, e);
            var n = this.validationError = this.validate(e, t) || null;
            return n ? (this.trigger("invalid", this, n, t || {}), !1) : !0;
        }
    });
    var p = e.Collection = function(e, t)
    {
        t || (t = {}),
        t.model && (this.model = t.model),
        void 0 !== t.comparator && (this.comparator = t.comparator),
        this.models = [],
        this._reset(),
        this.initialize.apply(this, arguments),
        e && this.reset(e, a.extend({
            silent: !0
        },
            t));
    };
    a.extend(p.prototype, d, {
        model: h,
        initialize: function()
        {
        },
        toJSON: function(e)
        {
            return this.map(function(t)
            {
                return t.toJSON(e);
            });
        },
        sync: function()
        {
            return e.sync.apply(this, arguments);
        },
        add: function(e, t)
        {
            e = a.isArray(e) ? e.slice() : [e],
            t || (t = {});
            var n, i, s, l, u, c, d, h, p, f;
            for (d = [], h = t.at, p = this.comparator && null == h && 0 != t.sort, f = a.isString(this.comparator) ? this.comparator : null, n = 0, i = e.length; n < i; n++)
            {
                (s = this._prepareModel(l = e[n], t)) ? (u = this.get(s)) ? t.merge && (u.set(l === s ? s.attributes : l, t), p && !c && u.hasChanged(f) && (c = !0)) : (d.push(s), s.on("all", this._onModelEvent, this), this._byId[s.cid] = s, null != s.id && (this._byId[s.id] = s)) : this.trigger("invalid", this, l, t);
            }
            if (d.length && (p && (c = !0), this.length += d.length, null != h ? r.apply(this.models, [h, 0].concat(d)) : o.apply(this.models, d)), c && this.sort({
                silent: !0
            }), t.silent)
            {
                return this;
            }
            for (n = 0, i = d.length; n < i; n++)
            {
                (s = d[n]).trigger("add", s, this, t);
            }
            return c && this.trigger("sort", this, t),
            this;
        },
        remove: function(e, t)
        {
            e = a.isArray(e) ? e.slice() : [e],
            t || (t = {});
            var n, i, o, s;
            for (n = 0, i = e.length; n < i; n++)
            {
                s = this.get(e[n]),
                s && (delete this._byId[s.id], delete this._byId[s.cid], o = this.indexOf(s), this.models.splice(o, 1), this.length--, t.silent || (t.index = o, s.trigger("remove", s, this, t)), this._removeReference(s));
            }
            return this;
        },
        push: function(e, t)
        {
            return e = this._prepareModel(e, t),
            this.add(e, a.extend({
                at: this.length
            },
                t)),
            e;
        },
        pop: function(e)
        {
            var t = this.at(this.length - 1);
            return this.remove(t, e),
            t;
        },
        unshift: function(e, t)
        {
            return e = this._prepareModel(e, t),
            this.add(e, a.extend({
                at: 0
            },
                t)),
            e;
        },
        shift: function(e)
        {
            var t = this.at(0);
            return this.remove(t, e),
            t;
        },
        slice: function(e, t)
        {
            return this.models.slice(e, t);
        },
        get: function(e)
        {
            return null == e ? void 0 : (this._idAttr || (this._idAttr = this.model.prototype.idAttribute), this._byId[e.id || e.cid || e[this._idAttr] || e]);
        },
        at: function(e)
        {
            return this.models[e];
        },
        where: function(e)
        {
            return a.isEmpty(e) ? [] : this.filter(function(t)
            {
                for (var n in e)
                {
                    if (e[n] !== t.get(n))
                    {
                        return !1;
                    }
                }
                return !0;
            });
        },
        sort: function(e)
        {
            if (!this.comparator)
            {
                throw Error("Cannot sort a set without a comparator");
            }
            return e || (e = {}),
            a.isString(this.comparator) || 1 === this.comparator.length ? this.models = this.sortBy(this.comparator, this) : this.models.sort(a.bind(this.comparator, this)),
            e.silent || this.trigger("sort", this, e),
            this;
        },
        pluck: function(e)
        {
            return a.invoke(this.models, "get", e);
        },
        update: function(e, t)
        {
            t = a.extend({
                add: !0,
                merge: !0,
                remove: !0
            },
                t),
            t.parse && (e = this.parse(e, t));
            var n, i, o, s, r = [],
                l = [],
                u = {};
            if (a.isArray(e) || (e = e ? [e] : []), t.add && !t.remove)
            {
                return this.add(e, t);
            }
            for (i = 0, o = e.length; i < o; i++)
            {
                n = e[i],
                s = this.get(n),
                t.remove && s && (u[s.cid] = !0),
                (t.add && !s || t.merge && s) && r.push(n);
            }
            if (t.remove)
            {
                for (i = 0, o = this.models.length; i < o; i++)
                {
                    n = this.models[i],
                    u[n.cid] || l.push(n);
                }
            }
            return l.length && this.remove(l, t),
            r.length && this.add(r, t),
            this;
        },
        reset: function(e, t)
        {
            t || (t = {}),
            t.parse && (e = this.parse(e, t));
            for (var n = 0,
                i = this.models.length; n < i; n++)
            {
                this._removeReference(this.models[n]);
            }
            return t.previousModels = this.models.slice(),
            this._reset(),
            e && this.add(e, a.extend({
                silent: !0
            },
                t)),
            t.silent || this.trigger("reset", this, t),
            this;
        },
        fetch: function(e)
        {
            e = e ? a.clone(e) : {},
            void 0 === e.parse && (e.parse = !0);
            var t = e.success;
            return e.success = function(e, n, i)
            {
                var o = i.update ? "update" : "reset";
                e[o](n, i),
                t && t(e, n, i);
            },
            this.sync("read", this, e);
        },
        create: function(e, t)
        {
            if (t = t ? a.clone(t) : {},
            !(e = this._prepareModel(e, t)))
            {
                return !1;
            }
            t.wait || this.add(e, t);
            var n = this,
                i = t.success;
            return t.success = function(e, t, o)
            {
                o.wait && n.add(e, o),
                i && i(e, t, o);
            },
            e.save(null, t),
            e;
        },
        parse: function(e)
        {
            return e;
        },
        clone: function()
        {
            return new this.constructor(this.models);
        },
        _reset: function()
        {
            this.length = 0,
            this.models.length = 0,
            this._byId = {};
        },
        _prepareModel: function(e, t)
        {
            if (e instanceof h)
            {
                return e.collection || (e.collection = this),
                e;
            }
            t || (t = {}),
            t.collection = this;
            var n = new this.model(e, t);
            return n._validate(e, t) ? n : !1;
        },
        _removeReference: function(e)
        {
            this === e.collection && delete e.collection,
            e.off("all", this._onModelEvent, this);
        },
        _onModelEvent: function(e, t, n, i)
        {
            ("add" !== e && "remove" !== e || n === this) && ("destroy" === e && this.remove(t, i), t && e === "change:" + t.idAttribute && (delete this._byId[t.previous(t.idAttribute)], null != t.id && (this._byId[t.id] = t)), this.trigger.apply(this, arguments));
        },
        sortedIndex: function(e, t, n)
        {
            t || (t = this.comparator);
            var i = a.isFunction(t) ? t : function(e)
            {
                return e.get(t);
            };
            return a.sortedIndex(this.models, e, i, n);
        }
    });
    var f = ["forEach", "each", "map", "collect", "reduce", "foldl", "inject", "reduceRight", "foldr", "find", "detect", "filter", "select", "reject", "every", "all", "some", "any", "include", "contains", "invoke", "max", "min", "toArray", "size", "first", "head", "take", "initial", "rest", "tail", "drop", "last", "without", "indexOf", "shuffle", "lastIndexOf", "isEmpty", "chain"];
    a.each(f,
        function(e)
        {
            p.prototype[e] = function()
            {
                var t = s.call(arguments);
                return t.unshift(this.models),
                a[e].apply(a, t);
            };
        });
    var m = ["groupBy", "countBy", "sortBy"];
    a.each(m,
        function(e)
        {
            p.prototype[e] = function(t, n)
            {
                var i = a.isFunction(t) ? t : function(e)
                {
                    return e.get(t);
                };
                return a[e](this.models, i, n);
            };
        });
    var g = e.Router = function(e)
    {
        e || (e = {}),
        e.routes && (this.routes = e.routes),
        this._bindRoutes(),
        this.initialize.apply(this, arguments);
    },
        v = /\((.*?)\)/g,
        _ = /(\(\?)?:\w+/g,
        C = /\*\w+/g,
        y = /[\-{}\[\]+?.,\\\^$|#\s]/g;
    a.extend(g.prototype, d, {
        initialize: function()
        {
        },
        route: function(t, n, i)
        {
            return a.isRegExp(t) || (t = this._routeToRegExp(t)),
            i || (i = this[n]),
            e.history.route(t, a.bind(function(o)
            {
                var s = this._extractParameters(t, o);
                i && i.apply(this, s),
                this.trigger.apply(this, ["route:" + n].concat(s)),
                this.trigger("route", n, s),
                e.history.trigger("route", this, n, s);
            },
                this)),
            this;
        },
        navigate: function(t, n)
        {
            return e.history.navigate(t, n),
            this;
        },
        _bindRoutes: function()
        {
            if (this.routes)
            {
                for (var e, t = a.keys(this.routes); null != (e = t.pop());)
                {
                    this.route(e, this.routes[e]);
                }
            }
        },
        _routeToRegExp: function(e)
        {
            return e = e.replace(y, "\\$&").replace(v, "(?:$1)?").replace(_,
                function(e, t)
                {
                    return t ? e : "([^/]+)";
                }).replace(C, "(.*?)"),
            RegExp("^" + e + "$");
        },
        _extractParameters: function(e, t)
        {
            return e.exec(t).slice(1);
        }
    });
    var P = e.History = function()
    {
        this.handlers = [],
        a.bindAll(this, "checkUrl"),
        "undefined" !== typeof window && (this.location = window.location, this.history = window.history);
    },
        T = /^[#\/]|\s+$/g,
        E = /^\/+|\/+$/g,
        S = /msie [\w.]+/,
        b = /\/$/;
    P.started = !1,
    a.extend(P.prototype, d, {
        interval: 50,
        getHash: function(e)
        {
            var t = (e || this).location.href.match(/#(.*)$/);
            return t ? t[1] : "";
        },
        getFragment: function(e, t)
        {
            if (null == e)
            {
                if (this._hasPushState || !this._wantsHashChange || t)
                {
                    e = this.location.pathname;
                    var n = this.root.replace(b, "");
                    e.indexOf(n) || (e = e.substr(n.length));
                }
                else
                {
                    e = this.getHash();
                }
            }
            return e.replace(T, "");
        },
        start: function(t)
        {
            if (P.started)
            {
                throw Error("Backbone.history has already been started");
            }
            P.started = !0,
            this.options = a.extend({},
                {
                    root: "/"
                },
                this.options, t),
            this.root = this.options.root,
            this._wantsHashChange = this.options.hashChange !== !1,
            this._wantsPushState = !!this.options.pushState,
            this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState);
            var n = this.getFragment(),
                i = document.documentMode,
                o = S.exec(navigator.userAgent.toLowerCase()) && (!i || i <= 7);
            this.root = ("/" + this.root + "/").replace(E, "/"),
            o && this._wantsHashChange && (this.iframe = e.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow, this.navigate(n)),
            this._hasPushState ? e.$(window).on("popstate", this.checkUrl) : this._wantsHashChange && "onhashchange" in window && !o ? e.$(window).on("hashchange", this.checkUrl) : this._wantsHashChange && (this._checkUrlInterval = setInterval(this.checkUrl, this.interval)),
            this.fragment = n;
            var s = this.location,
                r = s.pathname.replace(/[^\/]$/, "$&/") === this.root;
            return this._wantsHashChange && this._wantsPushState && !this._hasPushState && !r ? (this.fragment = this.getFragment(null, !0), this.location.replace(this.root + this.location.search + "#" + this.fragment), !0) : (this._wantsPushState && this._hasPushState && r && s.hash && (this.fragment = this.getHash().replace(T, ""), this.history.replaceState({},
                document.title, this.root + this.fragment + s.search)), this.options.silent ? void 0 : this.loadUrl());
        },
        stop: function()
        {
            e.$(window).off("popstate", this.checkUrl).off("hashchange", this.checkUrl),
            clearInterval(this._checkUrlInterval),
            P.started = !1;
        },
        route: function(e, t)
        {
            this.handlers.unshift({
                route: e,
                callback: t
            });
        },
        checkUrl: function()
        {
            var e = this.getFragment();
            return e === this.fragment && this.iframe && (e = this.getFragment(this.getHash(this.iframe))),
            e === this.fragment ? !1 : (this.iframe && this.navigate(e), this.loadUrl() || this.loadUrl(this.getHash()), void 0);
        },
        loadUrl: function(e)
        {
            var t = this.fragment = this.getFragment(e),
                n = a.any(this.handlers,
                    function(e)
                    {
                        return e.route.test(t) ? (e.callback(t), !0) : void 0;
                    });
            return n;
        },
        navigate: function(e, t)
        {
            if (!P.started)
            {
                return !1;
            }
            if (t && t !== !0 || (t = {
                trigger: t
            }), e = this.getFragment(e || ""), this.fragment !== e)
            {
                this.fragment = e;
                var n = this.root + e;
                if (this._hasPushState)
                {
                    this.history[t.replace ? "replaceState" : "pushState"]({},
                        document.title, n);
                }
                else
                {
                    if (!this._wantsHashChange)
                    {
                        return this.location.assign(n);
                    }
                    this._updateHash(this.location, e, t.replace),
                    this.iframe && e !== this.getFragment(this.getHash(this.iframe)) && (t.replace || this.iframe.document.open().close(), this._updateHash(this.iframe.location, e, t.replace));
                }
                t.trigger && this.loadUrl(e);
            }
        },
        _updateHash: function(e, t, n)
        {
            if (n)
            {
                var i = e.href.replace(/(javascript:|#).*$/, "");
                e.replace(i + "#" + t);
            }
            else
            {
                e.hash = "#" + t;
            }
        }
    }),
    e.history = new P;
    var w = e.View = function(e)
    {
        this.cid = a.uniqueId("view"),
        this._configure(e || {}),
        this._ensureElement(),
        this.initialize.apply(this, arguments),
        this.delegateEvents();
    },
        N = /^(\S+)\s*(.*)$/,
        I = ["model", "collection", "el", "id", "attributes", "className", "tagName", "events"];
    a.extend(w.prototype, d, {
        tagName: "div",
        $: function(e)
        {
            return this.$el.find(e);
        },
        initialize: function()
        {
        },
        render: function()
        {
            return this;
        },
        remove: function()
        {
            return this.$el.remove(),
            this.stopListening(),
            this;
        },
        setElement: function(t, n)
        {
            return this.$el && this.undelegateEvents(),
            this.$el = t instanceof e.$ ? t : e.$(t),
            this.el = this.$el[0],
            n !== !1 && this.delegateEvents(),
            this;
        },
        delegateEvents: function(e)
        {
            if (e || (e = a.result(this, "events")))
            {
                this.undelegateEvents();
                for (var t in e)
                {
                    var n = e[t];
                    if (a.isFunction(n) || (n = this[e[t]]), !n)
                    {
                        throw Error('Method "' + e[t] + '" does not exist');
                    }
                    var i = t.match(N),
                        o = i[1],
                        s = i[2];
                    n = a.bind(n, this),
                    o += ".delegateEvents" + this.cid,
                    "" === s ? this.$el.on(o, n) : this.$el.on(o, s, n);
                }
            }
        },
        undelegateEvents: function()
        {
            this.$el.off(".delegateEvents" + this.cid);
        },
        _configure: function(e)
        {
            this.options && (e = a.extend({},
                a.result(this, "options"), e)),
            a.extend(this, a.pick(e, I)),
            this.options = e;
        },
        _ensureElement: function()
        {
            if (this.el)
            {
                this.setElement(a.result(this, "el"), !1);
            }
            else
            {
                var t = a.extend({},
                    a.result(this, "attributes"));
                this.id && (t.id = a.result(this, "id")),
                this.className && (t["class"] = a.result(this, "className"));
                var n = e.$("<" + a.result(this, "tagName") + ">").attr(t);
                this.setElement(n, !1);
            }
        }
    });
    var O = {
        create: "POST",
        update: "PUT",
        patch: "PATCH",
        "delete": "DELETE",
        read: "GET"
    };
    e.sync = function(t, n, i)
    {
        var o = O[t];
        a.defaults(i || (i = {}), {
            emulateHTTP: e.emulateHTTP,
            emulateJSON: e.emulateJSON
        });
        var s = {
            type: o,
            dataType: "json"
        };
        if (i.url || (s.url = a.result(n, "url") || M()), null != i.data || !n || "create" !== t && "update" !== t && "patch" !== t || (s.contentType = "application/json", s.data = JSON.stringify(i.attrs || n.toJSON(i))), i.emulateJSON && (s.contentType = "application/x-www-form-urlencoded", s.data = s.data ? {
            model: s.data
        } : {}), i.emulateHTTP && ("PUT" === o || "DELETE" === o || "PATCH" === o))
        {
            s.type = "POST",
            i.emulateJSON && (s.data._method = o);
            var r = i.beforeSend;
            i.beforeSend = function(e)
            {
                return e.setRequestHeader("X-HTTP-Method-Override", o),
                r ? r.apply(this, arguments) : void 0;
            };
        }
        "GET" === s.type || i.emulateJSON || (s.processData = !1);
        var l = i.success;
        i.success = function(e)
        {
            l && l(n, e, i),
            n.trigger("sync", n, e, i);
        };
        var u = i.error;
        i.error = function(e)
        {
            u && u(n, e, i),
            n.trigger("error", n, e, i);
        };
        var c = i.xhr = e.ajax(a.extend(s, i));
        return n.trigger("request", n, c, i),
        c;
    },
    e.ajax = function()
    {
        return e.$.ajax.apply(e.$, arguments);
    };
    var x = function(e, t)
    {
        var n, i = this;
        n = e && a.has(e, "constructor") ? e.constructor : function()
        {
            return i.apply(this, arguments);
        },
        a.extend(n, i, t);
        var o = function()
        {
            this.constructor = n;
        };
        return o.prototype = i.prototype,
        n.prototype = new o,
        e && a.extend(n.prototype, e),
        n.__super__ = i.prototype,
        n;
    };
    h.extend = p.extend = g.extend = w.extend = P.extend = x;
    var M = function()
    {
        throw Error('A "url" property or function must be specified');
    };
}).call(this);
P.Module.define("AboutLinks", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("AddPin", [],
    function()
    {
        var e = "loading",
            t = "upload_button",
            n = "url_button",
            i = "recommended_button";
        return P.Module.extend({
            onContentReady: function()
            {
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onButtonClick: function(o)
            {
                var s, r = this,
                    a = o.target,
                    l = a.id,
                    u = !1,
                    c = this.options.board_id;
                a.$el.addClass(e),
                l === t ? s = {
                    name: "UploadPin",
                    options: {
                        default_board_id: c
                    }
                } : l === n ? s = {
                    name: "AddPinURL",
                    options: {
                        show_title: !0
                    }
                } : l === i && (s = {
                        name: "AddRecommendedPinsModal",
                        options: {
                            default_board_id: c
                        }
                    },
                u = !0),
                s && P.loadModule(s,
                    function(e)
                    {
                        r.modal.setModule(e),
                        u && r.modal.setTransparentContent(!0);
                    });
            }
        });
    }),
P.Module.define("AddPinRep", ["ModalTrigger"],
    function(e)
    {
        return e.extend({
            events: {
                click: "onClick"
            },
            onClick: function()
            {
                return this.showModal(),
                !1;
            }
        });
    }),
P.Module.define("AddPinURL", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.$(".standardForm"),
                    t = {
                        url: [P.Validator.Required(), P.Validator.URL()]
                    },
                    n = {
                        prevalidate: !0
                    };
                this.form = new P.Form(e, t, n),
                this.form.getField("url").placeholder(),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                if (!e.errors[0])
                {
                    var t = this.form.getValue("url");
                    this.navigate("/pin/find/?" + $.param({
                        url: t
                    }));
                }
            }
        });
    }),
P.Module.define("AddRecommendedPinsModal", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("AdhocFeedIndexPage", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("AdhocFeedPage", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("Analytics.Metric", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("Analytics.MetricChange", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("Analytics.MetricGraph", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .legendColorBox": "onClickLegend",
                "click .legendLabel": "onClickLegend",
                resize: "onResize"
            },
            graphContainer: function()
            {
                return void 0 === this.placeholder && (this.placeholder = $(".graphPlaceholder", this.el)),
                this.placeholder;
            },
            initialize: function()
            {
                this.placeholder = void 0,
                this.disabledSeries = {},
                this.resetCurrentHover();
            },
            onAddedToDom: function()
            {
                this._addedToDom = !0,
                this.trySetupGraph();
            },
            onContentReady: function()
            {
                this._contentReady = !0,
                this.trySetupGraph();
            },
            onRemoved: function()
            {
                this.hideDropdown();
            },
            resizeGraph: function()
            {
                this.updateGraph();
            },
            trySetupGraph: function()
            {
                this._addedToDom && this._contentReady && (this.listen(P.Viewport, P.CONST.EVENT_BODY_COLUMN_CHANGE, this.resizeGraph), this.updateGraph(), this.setupGraphClicks(), this.anchor = $("<em></em>").css({
                    position: "absolute"
                }).appendTo(this.$el));
            },
            onClickLegend: function(e)
            {
                var t = $(e.target).attr("data-index");
                this.toggleSeries(t);
            },
            toggleSeries: function(e)
            {
                this.disabledSeries[e] = !this.disabledSeries[e],
                this.updateGraph();
            },
            extractMetricSeries: function(e)
            {
                var t = this.data;
                return $.map(t,
                    function(t)
                    {
                        var n = 1e3 * t.timestamp,
                            i = t[e];
                        return [[n, i]];
                    });
            },
            buildTimeSeries: function()
            {
                for (var e = [], t = 0; t < this.options.metric_group.length; t++)
                {
                    var n = this.options.metric_group[t],
                        i = [],
                        o = 0 === t ? "#E6E6FF" : "#FAF0B4";
                    this.disabledSeries[t] !== !0 && (i = this.extractMetricSeries(n), o = 0 === t ? "#367CBD" : "#C06506");
                    var s = this.options.metric_type_map[n].graph_name;
                    e.push({
                        data: i,
                        label: s,
                        color: o,
                        points: {
                            show: !0,
                            fill: !0,
                            fillColor: o
                        }
                    });
                }
                return e;
            },
            updateGraph: function()
            {
                var e = this.buildTimeSeries();
                this.drawGraph(e);
            },
            tickFormatterY: function(e, t)
            {
                return e < 0 ? "" : t.max < 1e6 ? e.toFixed(t.tickDecimals) : (e /= 1e6, e.toFixed(1) + "m");
            },
            timeFormatter: function(e, t)
            {
                if (e < t.datamin || e > t.datamax)
                {
                    return "";
                }
                var n = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
                    i = new Date(e),
                    o = n[i.getUTCDay()],
                    s = i.getUTCMonth() + 1,
                    r = i.getUTCDate();
                return s + "/" + r + "<br/>" + o;
            },
            seriesMinMax: function(e, t)
            {
                for (var n = 0,
                    i = Number.MAX_VALUE,
                    o = 0; o < e.length; o++)
                {
                    for (var s = e[o].data, r = 0; r < s.length; r++)
                    {
                        var a = s[r][t];
                        n = n > a ? n : a,
                        i = i < a ? i : a;
                    }
                }
                return {
                    min: i,
                    max: n
                };
            },
            seriesMinMaxY: function(e)
            {
                var t = this.seriesMinMax(e, 1);
                return t.min -= .35 * t.max,
                t.max += .3 * t.max,
                t;
            },
            seriesMinMaxX: function(e)
            {
                var t = 864e5,
                    n = this.seriesMinMax(e, 0),
                    i = n.max - n.min,
                    o = .08 * i;
                return n.max += Math.max(t, o),
                n.min -= Math.max(t, o),
                n;
            },
            drawGraph: function(e)
            {
                var t = this.graphContainer(),
                    n = this.seriesMinMaxX(e),
                    i = this.seriesMinMaxY(e),
                    o = {
                        series: {
                            shadowSize: 1,
                            lines: {
                                show: !0
                            },
                            points: {
                                show: !0,
                                lineWidth: 1,
                                fill: !0,
                                radius: 5
                            }
                        },
                        legend: {
                            margin: [140, 10],
                            noColumns: 2,
                            backgroundOpacity: 0,
                            labelBoxBorderColor: "rgba(0,0,0,0)"
                        },
                        grid: {
                            backgroundColor: "rgb(249, 249, 249)",
                            borderColor: "rgb(230, 230, 230)",
                            borderWidth: 0,
                            minBorderMargin: 0,
                            labelMargin: 0,
                            clickable: !0,
                            hoverable: !0,
                            axisMargin: 0
                        },
                        yaxis: {
                            tickColor: "rgb(230, 230, 230)",
                            reserveSpace: !0,
                            max: i.max,
                            min: i.min,
                            tickFormatter: this.tickFormatterY
                        },
                        xaxis: {
                            tickColor: "rgb(230, 230, 230)",
                            mode: "time",
                            min: n.min,
                            max: n.max,
                            tickFormatter: this.timeFormatter
                        }
                    };
                $.plot(t, e, o);
            },
            checkAndSetNewHover: function(e)
            {
                var t = {
                    dataIndex: e.dataIndex,
                    seriesIndex: e.seriesIndex
                };
                return t.dataIndex === this.currentHover.dataIndex && t.seriesIndex === this.currentHover.seriesIndex ? !1 : (this.currentHover = t, !0);
            },
            onPointHovered: function(e)
            {
                if (this.checkAndSetNewHover(e) !== !1)
                {
                    var t = this.getChildById("metricPoint");
                    this.pointDropdown = t._dropdown;
                    var n = this.pointDropdown.getChildById("dropdownModule");
                    n.updateData({
                        seriesIndex: e.seriesIndex,
                        date: new Date(e.datapoint[0]),
                        value: e.datapoint[1]
                    }),
                    this.anchor.css({
                        top: e.pageY + 10,
                        left: e.pageX
                    }),
                    this.pointDropdown.options.anchor = $(this.anchor),
                    this.pointDropdown.show();
                }
            },
            onPointUnhovered: function()
            {
                this.hideDropdown();
            },
            hideDropdown: function()
            {
                this.pointDropdown && this.pointDropdown.hide(),
                this.resetCurrentHover();
            },
            resetCurrentHover: function()
            {
                this.currentHover = {};
            },
            setupGraphClicks: function()
            {
                var e = this,
                    t = this.graphContainer();
                t.bind("plothover",
                    function(t, n, i)
                    {
                        i ? e.onPointHovered(i) : e.onPointUnhovered(n);
                    });
            }
        });
    }),
P.Module.define("Analytics.MetricOverview", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("Analytics.MetricPoint", [],
    function()
    {
        return P.Module.extend({
            events: {},
            updateData: function(e)
            {
                this.updateValue(e.value),
                this.updateDate(e.date),
                this.updateMetricClass(e.seriesIndex);
            },
            updateDate: function(e)
            {
                var t = e.days[e.getUTCDay()];
                this.$(".day").text(t);
                var n = e.getMonthName(),
                    i = n + " " + e.getUTCDate() + ", " + e.getFullYear();
                this.$(".date").text(i);
            },
            updateValue: function(e)
            {
                this.$(".value").text(e.toLocaleString());
            },
            updateMetricClass: function(e)
            {
                this.$(".value").removeClass("metric-primary metric-secondary");
                var t = "metric-primary";
                1 === e && (t = "metric-secondary"),
                this.$(".value").addClass(t);
            }
        });
    }),
P.Module.define("Analytics.MetricRecommendation", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .recommendationWrapper": "onClick"
            },
            onClick: function(e)
            {
                e.preventDefault();
                var t = parseInt($(e.target).attr("data-index"), 10);
                return this.showModal(t),
                !1;
            },
            showModal: function(e)
            {
                var t = this;
                this.showLoading();
                var n = {
                    name: "Analytics.MetricTipModal",
                    options: {
                        tipIndex: e,
                        tips: this.data
                    }
                };
                P.loadModule(n,
                    function(e)
                    {
                        P.trackGAEvent("analytics_tips", P.CONST.GA_ACTION_OPEN_MODAL),
                        t.hideLoading(),
                        t.showInModal(e);
                    });
            }
        });
    }),
P.Module.define("Analytics.MetricTipModal", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .nextTip": "nextTip",
                "click .prevTip": "prevTip"
            },
            onContentReady: function()
            {
                this.currentTip = this.options.tipIndex,
                this.tips = this.$(".tipGroup"),
                this.showTip(this.currentTip);
            },
            showTip: function(e)
            {
                if (!(e >= this.tips.length || e < 0))
                {
                    this.currentTip = e;
                    var t = this;
                    this.tips.each(function(n, i)
                    {
                        var o = e === n;
                        o ? ($(i).show(), t.$("h1").text($(i).attr("data-title"))) : $(i).hide();
                    }),
                    this.updateButtons(e);
                }
            },
            updateButtons: function(e)
            {
                var t = e < this.tips.length - 1;
                this.toggleButton("nextTipButton", t);
                var n = e > 0;
                this.toggleButton("prevTipButton", n);
            },
            toggleButton: function(e, t)
            {
                t ? this.getChildById(e).enable() : this.getChildById(e).disable();
            },
            nextTip: function()
            {
                this.showTip(this.currentTip + 1);
            },
            prevTip: function()
            {
                this.showTip(this.currentTip - 1);
            }
        });
    }),
P.Module.define("Analytics.MetricTypeInfo", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("AnnotationFeedPage", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .annotationText a": "onClick"
            },
            onClick: function(e)
            {
                var t = $(e.target),
                    n = this.$(".feedName");
                n.text(t.text()),
                this.$(".highlight").removeClass("highlight"),
                t.parent().addClass("highlight"),
                this.updateFeedGrid(new P.Resource("AnnotatedPinsResource", {
                    term: t.text()
                }));
            },
            updateFeedGrid: function(e)
            {
                var t = this.getChildById("feedGrid"),
                    n = this;
                this.$el.css("height", this.$el.height()),
                t.emptyItems(),
                t.setItemsResource(e),
                t.renderItems(function()
                {
                    P.NOOP(),
                    n.$el.css("height", "auto");
                });
            }
        });
    }),
P.Module.define("App", ["Header", "Grid", "Modal", "ScrollToTop"],
    function()
    {
        var e = "mainModule",
            t = "Closeup",
            n = 500,
            i = "HomePage",
            o = {
                REPLACE: 0,
                REPLACE_TOP: 1,
                APPEND: 2,
                CLOSE: 3,
                IGNORE: 4
            },
            s = P.Module.extend({
                events: {},
                initialize: function()
                {
                    this.modalManager = null,
                    this.historyManager = new P.HistoryManager,
                    this.backgroundModule = null,
                    this.canUpdatePageInfo = !1,
                    P.currentUser.isAuthenticated() || P.currentUser.attemptLogin();
                },
                onAddedToDom: function()
                {
                    P.router.start(),
                    P.AppVersion.setup(P.CONTEXT.app_version),
                    this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate),
                    this.childListen("modal", this.onChildModal),
                    this.childListen("close", this.onChildClose),
                    this.childListen("switchToOld", this.switchToOld),
                    this.listen(P.router, "route", this.onRoute),
                    this.listen(P.router, "404", this.onRouteNotFound),
                    this.modalManager || (this.modalManager = P.ModalManager.instance());
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_PAGE_INFO] = this.onPageInfoChange,
                    this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_SITE, e);
                },
                showWelcomeDialog: function()
                {
                    Cookie.unset(P.CONST.COOKIE_SHOW_WELCOME);
                    var e = {
                        name: "ConfirmDialog",
                        options: {
                            template: "welcome"
                        }
                    },
                        t = this;
                    P.loadModule(e,
                        function(e)
                        {
                            t.listen(e, P.CONST.EVENT_DESTROYED,
                                function()
                                {
                                    var e = t._getCurrentMainModule();
                                    e.className === i && e.showsFollowingFeed() && P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_TUTORIAL, P.CONST.PUBSUB_TOPIC_TUTORIAL_CATEGORIES);
                                }),
                            t.modalManager.showInModal(e);
                        });
                },
                showFastFollowDialog: function()
                {
                    var e = this._getCurrentMainModule(),
                        t = e.options.from_fast_follow,
                        n = P.currentUser.get("show_fast_follow");
                    if (!t && n && !this.isTutorialActive() && "HomePage" === e.className)
                    {
                        var i = {
                            id: "fastFollow",
                            name: "FastFollow",
                            resource: {
                                name: "UserResource",
                                options: {
                                    username: P.currentUser.get("username"),
                                    field_set_key: "fast_follow"
                                }
                            }
                        };
                        P.loadModule(i, _.bind(function(e)
                        {
                            this.showInModal(e, {
                                can_dismiss: !1,
                                mask_type: "dark"
                            });
                        },
                            this));
                    }
                },
                isTutorialActive: function()
                {
                    return P.TutorialManager.instance().isTutorialActive();
                },
                onContentReady: function()
                {
                    P.trackGAPageview();
                    var t = this._getCurrentMainModule();
                    this.setChildId(t, e),
                    this.historyManager.start(t),
                    this.historyManager.setPageInfo(P.PAGE_INFO);
                    var n = Cookie.get(P.CONST.COOKIE_SHOW_WELCOME);
                    if (n)
                    {
                        switch (n)
                        {
                            case "new":
                                P.TutorialManager.instance().startTutorial("newUser");
                                break;
                            case "existing":
                                P.TutorialManager.instance().startTutorial("existingUser");
                                break;
                            default:
                                this.showWelcomeDialog();
                        }
                        Cookie.unset(P.CONST.COOKIE_SHOW_WELCOME);
                    }
                    else
                    {
                        P.TutorialManager.instance().resumeTutorial();
                    }
                    if (this.showFastFollowDialog(), this.updateScrollWatchers(this._getCurrentMainModule()), P.e.fr)
                    {
                        var i = {
                            name: "PinCreate",
                            options: {
                                action: "repin",
                                is_template_module: !0
                            }
                        };
                        P.loadModule(i,
                            function(e)
                            {
                                e.render(function()
                                {
                                    var t = P.TemplateModuleLoader.instance();
                                    t.registerTemplateModule(e);
                                });
                            });
                    }
                },
                updateScrollWatchers: function(e)
                {
                    var t = this.getChildById("scrollToTop");
                    t && t.setScroller(e.getScrollableElement());
                },
                onRemovedFromDom: function()
                {
                    P.router.stop(),
                    this._removeListeners();
                },
                onChildNavigate: function(e)
                {
                    if (this.midNavigate)
                    {
                        return e.stopPropagation(),
                        void 0;
                    }
                    var t = e.data.url;
                    if (P.isOffsiteUrl(t) || (this.midNavigate = !0), P.AppVersion.invalid)
                    {
                        return window.location.href = t,
                        void 0;
                    }
                    this.log.debug("App got navigate event from child", e.target, "for url:", t);
                    var n = {
                        handled: !!e.data.handled,
                        evt: e
                    };
                    this.historyManager.navigate(t, n),
                    e.stopPropagation();
                },
                onChildModal: function(e)
                {
                    this.log.debug("Got modal event from child", e.target, "for module:", e.data.module),
                    e.stopPropagation(),
                    this.modalManager.showInModal(e.data.module, e.data.extraOptions || {},
                        e.target);
                },
                onChildClose: function()
                {
                    this.historyManager.closeCurrentModule();
                },
                onRoute: function(e)
                {
                    if (P.AppVersion.invalid)
                    {
                        return window.location.reload(),
                        void 0;
                    }
                    this.log.debug("onRoute", e),
                    P.trackGAPageview(e.module);
                    var t = e.module,
                        n = e.options,
                        i = e.resource,
                        o = "https:" === window.location.protocol;
                    if (e.https && !o)
                    {
                        return window.location.replace(window.location.href.replace(/http:\/\//, "https://")),
                        void 0;
                    }
                    if (!e.https && o)
                    {
                        return window.location.replace(window.location.href.replace(/https:\/\//, "http://")),
                        void 0;
                    }
                    this.isTutorialActive() || this.modalManager.removeAllModals(!0);
                    var s = this;
                    P.Loader.require([t], P.stopwatch.wrapContinuation("P.Loader.require callback",
                        function(t)
                        {
                            var o = s.historyManager.getModule(t, e.navigateData);
                            return s._getCurrentMainModule() ? (s.updateMainModule(o, n, i, e.navigateData), void 0) : (window.location.reload(), void 0);
                        }));
                    var r = this.historyManager.getPageInfo();
                    r && this.setPageInfo(r),
                    this.canUpdatePageInfo = !r;
                },
                onRouteNotFound: function()
                {
                    window.location.reload();
                },
                onPageInfoChange: function(e, t, n)
                {
                    this.canUpdatePageInfo && (this.historyManager.setPageInfo(n), this.setPageInfo(n), this.canUpdatePageInfo = !1);
                },
                setPageInfo: function(e)
                {
                    e.title && $(document).attr("title", e.title),
                    $("head meta[data-app]").remove();
                    var t = [];
                    _.each(e.meta,
                        function(e, n)
                        {
                            t.push($("<meta>").prop({
                                name: n,
                                property: n,
                                content: e,
                                "data-app": 1
                            }));
                        }),
                    $("head").append(t);
                },
                startModuleTransition: function(e)
                {
                    var t = this;
                    e.fadeOut(),
                    clearTimeout(this._loaderTimeout),
                    this._loaderTimeout = setTimeout(function()
                    {
                        t.loadingShown = !0,
                        t.showLoading(!0);
                    },
                        n, "App loader");
                },
                stopModuleTransition: function(e)
                {
                    clearTimeout(this._loaderTimeout),
                    e.fadeIn(),
                    this.loadingShown && (this.hideLoading(), this.loadingShown = !1);
                },
                _getCurrentMainModule: function()
                {
                    var t = this.getChildById(e);
                    return t ? t : this.children[this.children.length - 1];
                },
                updateMainModule: function(e, n, i, s)
                {
                    var r = e.module,
                        a = e.backgroundModule,
                        l = this._getCurrentMainModule();
                    l.getScrollableElement().scrollTop(),
                    l.saveExtraState(!0),
                    this.log.debug("Current:", l.className, "New:", r.className);
                    var u = this._getNextAction(l, r, a, s),
                        c = u === o.REPLACE && l.className !== t && r.className !== t;
                    c && this.startModuleTransition(l),
                    r.clearFades();
                    var d = this._getCanClose(l, e, u);
                    null !== d && (n.can_close = d);
                    var h = null === d || d === !1;
                    P.Body.setScrolling(h);
                    var p = this,
                        f = P.stopwatch.wrapContinuation("updateMainModule cleanup",
                            function()
                            {
                                p.midNavigate = !1,
                                c && p.stopModuleTransition(r),
                                p.updateScrollWatchers(r);
                            });
                    s.currentModule = l,
                    r.setAsMainModule(n, i, s, P.stopwatch.wrapContinuation(P.CONST.STOPWATCH_SET_AS_MAIN_MODULE_SUCCESS,
                            function()
                            {
                                p._performNextAction(u, l, e, s),
                                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_MAIN_MODULE, P.CONST.PUBSUB_TOPIC_MAIN_MODULE_NEW, _.bind(p._getCurrentMainModule, p)),
                                p.showFastFollowDialog(),
                                f();
                            }), P.stopwatch.wrapContinuation("setAsMainModule failure",
                                function()
                                {
                                    p.historyManager.cancelNavigation(),
                                    f();
                                }));
                },
                _getNextAction: function(e, n, i, s)
                {
                    var r = null;
                    return r = e === n ? o.IGNORE : n.className !== t ? e.className === t && e.options.can_close && this.backgroundModule && n === this.backgroundModule ? o.CLOSE : o.REPLACE : s.fromNavigate ? e.className === t ? e.options.can_close ? o.REPLACE_TOP : o.REPLACE : o.APPEND : e === i && n.className === t ? o.APPEND : o.REPLACE;
                },
                _getCanClose: function(e, n, i)
                {
                    var s = n.module,
                        r = n.backgroundModule;
                    if (s.className !== t)
                    {
                        return null;
                    }
                    var a = e.className === t,
                        l = !!e.options.can_close;
                    switch (i)
                    {
                        case o.REPLACE:
                            return !!r;
                        case o.REPLACE_TOP:
                            return l;
                        case o.APPEND:
                            return !a || l;
                        case o.IGNORE:
                            return l;
                    }
                    return null;
                },
                _performNextAction: function(t, n, i, s)
                {
                    var r = this,
                        a = i.module,
                        l = i.backgroundModule;
                    n.getElement();
                    var u = a.getElement(),
                        c = t !== o.IGNORE;
                    if (t === o.IGNORE)
                    {
                        r.backgroundModule && r.historyManager.updateBackgroundModule(r.backgroundModule, s);
                    }
                    else if (t === o.CLOSE)
                    {
                        r.backgroundModule = null,
                        n.detachElement(),
                        r.removeChildId(n);
                    }
                    else if (t === o.REPLACE)
                    {
                        if (r.backgroundModule !== l && (r.backgroundModule && (r.backgroundModule.detachElement(), r.backgroundModule = null), l))
                        {
                            var d = l.getElement();
                            l !== n && (r.$(".mainContainer").append(d), r.addChild(l)),
                            r.backgroundModule = l;
                        }
                        n !== l && (this.removeChildId(n), n.detachElement()),
                        r.removeChildId(n),
                        u.css("min-height", P.Viewport.height);
                        var h = r.backgroundModule ? $(".appendedContainer") : $(".mainContainer");
                        h.append(u),
                        r.addChild(a);
                    }
                    else
                    {
                        t === o.REPLACE_TOP ? (n.detachElement(), u.css("min-height", P.Viewport.height), $(".appendedContainer").append(u), r.addChild(a), r.historyManager.updateBackgroundModule(r.backgroundModule, s)) : t === o.APPEND && (r.backgroundModule = n, r.removeChildId(n), u.css("min-height", P.Viewport.height), $(".appendedContainer").append(u), r.addChild(a), r.historyManager.updateBackgroundModule(r.backgroundModule, s));
                    }
                    c && (r.setChildId(a, e), a.restoreExtraState(!0));
                },
                showMask: function()
                {
                    var e = this.getMask();
                    e.addClass("visible");
                },
                switchToOld: function(e)
                {
                    this.modalManager.removeAllModals(),
                    this.getScrollableElement().scrollTop(0),
                    this.$el.empty();
                    var t = this,
                        n = {
                            name: "ConfirmDialog",
                            options: {
                                template: "goodbye"
                            }
                        },
                        i = function()
                        {
                            var t = e.data;
                            P.changeWindowLocation(t, !1);
                        };
                    P.loadModule(n,
                        function(e)
                        {
                            t.listen(e, "rendered",
                                function()
                                {
                                    var e = $(".oldHeader");
                                    $("body").append(e);
                                }),
                            t.listen(e, P.CONST.EVENT_DESTROYED, i),
                            t.showInModal(e);
                        });
                },
                debugNumGridItems: function()
                {
                    for (var e, t = [], n = [this]; n.length > 0;)
                    {
                        e = n.pop(),
                        "GridItems" === e.className && t.push(e),
                        n = n.concat(e.children);
                    }
                    return _.each(t,
                        function(e, t)
                        {
                            for (var n = e.parent,
                                i = e.className + " has " + e.children.length + " children"; n;)
                            {
                                i = n.className + "->" + i,
                                n = n.parent;
                            }
                            this.log.debug(t + 1 + ": " + i);
                        }),
                    0 === t.length && this.log.debug("There are no grids in the page."),
                    ":)";
                }
            });
        return P.Errors.wrap(s.prototype, ["initialize", "onAddedToDom", "onChildNavigate", "onChildModal", "onContentReady", "onRoute", "onRouteNotFound"]),
        P.stopwatch.wrapMethods(s.prototype, "App", ["onChildClose", "onRoute", "updateMainModule"]),
        s;
    }),
P.Module.define("AuthHomePage", ["NewPinsIndicator"],
    function(e)
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this._setUpFastFollow(),
                P.e.nps && (this.listen(P.Updater.instance(), "new_pins_count", this.onNewPins), this.setRecentPinId());
            },
            _setUpFastFollow: function()
            {
                this.inDom && this.contentReady;
            },
            onBoardInteraction: function()
            {
                this.render();
            },
            onAddedToDom: function()
            {
                this._setUpFastFollow(),
                this.setRecentPinId();
            },
            onRemovedFromDom: function()
            {
                P.Updater.instance().setRecentPinId(null);
            },
            setRecentPinId: function()
            {
                P.e.nps && P.Updater.instance().setRecentPinId(this.getRecentPinId());
            },
            onNewPins: function(e)
            {
                var t = this.ensureNewPinsIndicator();
                (e || t.options.count) && e !== t.options.count && (P.setTitlePrefix(e), t.options.count = e, t.render(function()
                {
                    e && t.show();
                }));
            },
            onNewPinsClick: function(e)
            {
                e.stopPropagation();
                var t = this,
                    n = this.ensureNewPinsIndicator(),
                    i = this.getChildById("feedGrid");
                n.hide(),
                i && $("body,html").animate({
                        scrollTop: 0
                    },
                    {
                        duration: 300,
                        complete: _.once(function()
                        {
                            i.prependNewItems(n.options.count,
                                function()
                                {
                                    t.setRecentPinId();
                                }),
                            n.options.count = 0;
                        })
                    }),
                P.setTitlePrefix(null);
            },
            ensureNewPinsIndicator: function()
            {
                var t = this.getChildById("newPins");
                return t || (t = new e({
                    id: "newPins"
                }), this.listen(t, "click", this.onNewPinsClick), this.appendChild(t), t.hide()),
                t;
            },
            showsFollowingFeed: function()
            {
                return !!this.getChildById("feedGrid");
            },
            getRecentPinId: function()
            {
                var e = this.getChildById("feedGrid");
                if (!e)
                {
                    return null;
                }
                var t = e.getFirstGridItem("Pin");
                return t ? t.getPinId() : void 0;
            }
        });
    }),
P.Module.define("Board", ["Dropdown"],
    function(e)
    {
        var t = "noShadow",
            n = "follow_view";
        return P.Module.extend({
            events: {
                "click .dismiss": "onDismissClick"
            },
            getOwnedScrollables: function()
            {
                return this.$(".pinGridWrapper");
            },
            onContentReady: function()
            {
                var e = this.data && this.data.id;
                if (e)
                {
                    var i = {};
                    i[P.CONST.PUBSUB_TOPIC_BOARD_COVER_UPDATED] = this.onBoardCoverUpdated,
                    i[P.CONST.PUBSUB_TOPIC_BOARD_DELETED] = this.onBoardDeleted,
                    i[P.CONST.PUBSUB_TOPIC_BOARD_UPDATED] = this.onBoardUpdated,
                    this.pubsubSubscribe(e, i);
                }
                "boardPinsGrid" === this.options.view_type && (this._maxBoardPinsGridHeight = this.$el.css("max-height").replace(/[^0-9]/g, ""), this.$el.outerHeight() < this._maxBoardPinsGridHeight && this.$el.addClass(t)),
                this.options.view_type === n && this.initHoverListeners();
            },
            onDismissClick: function()
            {
                this.dismissed = !0,
                this.triggerEvent(P.CONST.EVENT_DISMISS, null, !0);
            },
            onBoardUpdated: function()
            {
                this.render();
            },
            onBoardDeleted: function()
            {
                this.destroy();
            },
            onBoardHoverEnter: function()
            {
                this.$el.isHovering() && this._dropdown.show();
            },
            onBoardHoverExit: function()
            {
                this._dropdown.getElement().isHovering() || this._dropdown.hide();
            },
            onBoardCoverUpdated: function(e, t, n)
            {
                this.setBoardCover(n);
            },
            positionBoardPinsGrid: function()
            {
                var e = this.getChildById("pinGrid");
                e.$(".activeItem").focus();
            },
            initHoverListeners: function()
            {
                this._hoverIntent || (this._hoverIntent = new P.HoverIntent(this.getElement(), {
                        enterDelay: 500,
                        exitDelay: 200
                    }), this.listen(this, P.CONST.EVENT_NAVIGATE, this.onBoardHoverExit), this.listen(this._hoverIntent, P.CONST.EVENT_HOVERINTENT_ENTER_COMPLETE, this.onBoardHoverEnter), this.listen(this._hoverIntent, P.CONST.EVENT_HOVERINTENT_OUT_COMPLETE, this.onBoardHoverExit), this.setActiveStyle = P.NOOP, this.isClickButton = function()
                    {
                        return !1;
                    },
                this._dropdown = new e({
                    options: {
                        anchor: this.getElement(),
                        class_name: "followViewHover underneathHeader",
                        position_point: "RIGHT_TOP",
                        module: {
                            name: "Board",
                            options: {
                                view_type: "boardPinsGrid",
                                scrollable: !0,
                                prevent_default_scroll: !0,
                                board_follow_button_options: {
                                    board_id: this.resource.options.board_id
                                }
                            },
                            resource: {
                                name: "BoardResource",
                                options: {
                                    board_id: this.resource.options.board_id
                                }
                            }
                        }
                    }
                }), this.appendChild(this._dropdown), this.$el.initHovering(), this._dropdown.getElement().initHovering());
            },
            setBoardCover: function(e)
            {
                var t = e.url,
                    n = e.crop_x,
                    i = e.crop_y,
                    o = e.nativeHeight,
                    s = e.nativeWidth,
                    r = e.scale,
                    a = this.$(".boardCoverWrapper img");
                a.attr("src", t).css({
                    height: o * r,
                    left: -n,
                    "max-width": "none",
                    position: "absolute",
                    top: -i,
                    width: s * r
                });
                var l = this.getChildById("boardCoverEditButton"),
                    u = l.options.submodule.options;
                u.board_cover_edit_options.cover_pin_id = e.pin_id;
            },
            disabledButtons: [],
            disable: function()
            {
                this.$el.find(".hoverMask").addClass("notNavigatable"),
                this.disabledButtons = [];
                var e = this;
                _.each(this.getChildrenByModuleName("ShowModalButton"),
                    function(t)
                    {
                        t.isDisabled() || (t.disable(), e.disabledButtons.push(t));
                    });
            },
            enable: function()
            {
                this.$el.find(".hoverMask").removeClass("notNavigatable"),
                _.each(this.disabledButtons,
                    function(e)
                    {
                        e.enable();
                    });
            }
        });
    }),
P.Module.define("BoardCollaboratorInvitesBase", [],
    function()
    {
        return P.Module.extend({
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_INVITE_USER, this.onChildInviteUser),
                this.childListen(P.CONST.EVENT_INVITE_EMAIL, this.onChildInviteEmail);
            },
            onChildInviteUser: function(e)
            {
                var t = this.getChildById("boardInviteForm");
                t.showLoading();
                var n = e.data.userId,
                    i = {
                        board_id: this.getBoardId(),
                        invited_user_id: n
                    },
                    o = new P.Resource("BoardInviteResource", i);
                o.call("create", {
                    success: function()
                    {
                        t.clearTypeahead();
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            },
            getBoardId: function()
            {
                return this.resource.options.board_id;
            },
            onChildInviteEmail: function(e)
            {
                var t = this.getChildById("boardInviteForm");
                t.showLoading();
                var n = e.data.email,
                    i = {
                        board_id: this.getBoardId(),
                        email: n
                    },
                    o = new P.Resource("BoardEmailInviteResource", i);
                o.call("create", {
                    success: function()
                    {
                        var e = _.template(P.string("successInviteSentToEmail"));
                        t.clearTypeahead();
                        var i = $("<div class='alert'>" + e({
                            email: n
                        }) + "</div>");
                        i.hide().insertAfter(t.$el).fadeIn(function()
                        {
                            i.delay(5e3).fadeOut(function()
                            {
                                i.remove();
                            });
                        });
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("BoardCollaborators", ["BoardCollaboratorInvitesBase"],
    function(e)
    {
        return e.extend({
            onContentReady: function()
            {
                this.boardInviteForm = this.getChildById("boardInviteForm");
                var e = this.getBoardId();
                if (e)
                {
                    var t = {};
                    t[P.CONST.PUBSUB_TOPIC_BOARD_UPDATED] = this.onBoardUpdated,
                    this.pubsubSubscribe(e, t);
                }
            },
            onBoardUpdated: function()
            {
                this.render();
            }
        });
    }),
P.Module.define("BoardCoverEdit", [],
    function()
    {
        return P.Module.extend({
            pins: null,
            index: null,
            prefetchBuffer: 10,
            events: {
                "click .previous": "previous",
                "click .next": "next"
            },
            initialize: function()
            {
                _.bindAll(this, "onKeyup", "next", "previous"),
                this.$img = $("<img>");
            },
            _positionIfReady: function()
            {
                !this._positioned && this.inDom && this.contentReady && (this._positioned = !0, this.imageCrop = this.getChildByModuleName("ui.ImageCrop"), this.listen($("body"), "keyup", this.onKeyup), this.coverPinId = this.options.cover_pin_id, this._initializePins(!0));
            },
            _initializePins: function(e)
            {
                if (e && null !== this.coverPinId)
                {
                    var t = {
                        id: this.coverPinId,
                        field_set_key: "board_cover_picker"
                    },
                        n = new P.Resource("PinResource", t),
                        i = this;
                    n.call("get", {
                        success: function(e)
                        {
                            i._appendPinsFromData([e.resource_response.data]),
                            i._initializePins();
                        },
                        error: function()
                        {
                            i.coverPinId = null,
                            i._initializePins();
                        }
                    });
                }
                else
                {
                    this._appendPinsFromData(this.data),
                    this.setIndex(0),
                    this.updateButtons();
                }
            },
            _appendPinsFromData: function(e)
            {
                this.pins || (this.pins = []);
                var t = this;
                _.each(e,
                    function(e)
                    {
                        var n = {
                            id: e.id,
                            url: e.images["236x"].url
                        };
                        n.id === t.coverPinId && t.pins.length || t.pins.push(n);
                    });
            },
            onAddedToDom: function()
            {
                this._positionIfReady();
            },
            onContentReady: function()
            {
                this._positionIfReady();
            },
            onKeyup: function(e)
            {
                null !== this.index && (e.keyCode === P.keyCode.LEFT ? this.previous() : e.keyCode === P.keyCode.RIGHT && this.next());
            },
            requestMoreIfNeeded: function()
            {
                if (!(this.index + this.prefetchBuffer < this.pins.length) && !this.resource.atEnd())
                {
                    var e = this;
                    this.resource.call("get", {
                        options: this.options,
                        success: function(t)
                        {
                            e.data = t.resource_response.data,
                            e._appendPinsFromData(e.data);
                        },
                        error: function()
                        {
                            e.data = [];
                        }
                    });
                }
            },
            next: function()
            {
                if (this.requestMoreIfNeeded(), this.index === this.pins.length - 1)
                {
                    return !1;
                }
                var e = this.index + 1;
                return this.setIndex(e),
                !1;
            },
            previous: function()
            {
                var e = this.index - 1;
                return this.setIndex(e),
                !1;
            },
            setIndex: function(e)
            {
                var t = this.pins[e];
                t && (this.imageCrop.setImage(t.url), this.index = e, this.preload([this.index - 2, this.index - 1, this.index + 1, this.index + 2]), this.updateButtons());
            },
            preload: function(e)
            {
                var t = this;
                _.each(e,
                    function(e)
                    {
                        var n = t.pins[e];
                        n && P.preloadImage(n.url);
                    });
            },
            updateButtons: function()
            {
                var e = 0 < this.index;
                this.$(".previous").toggle(e);
                var t = this.index < this.pins.length - 1 || !this.resource.atEnd();
                this.$(".next").toggle(t);
            },
            getBoardCoverData: function()
            {
                var e = this.pins[this.index].id,
                    t = this.pins[this.index].url,
                    n = _.extend({},
                        {
                            pin_id: e,
                            pin_image_url: t
                        },
                        this.imageCrop.getCropData());
                return n;
            }
        });
    }),
P.Module.define("BoardCoverEditPage", [],
    function()
    {
        var e = P.Module.extend({
            events: {
                "click .save": "save",
                "click .cancel": "cancel"
            },
            save: function()
            {
                P.trackGAEvent("board_edit_cover", P.CONST.GA_ACTION_CLICK_SUBMIT);
                var e = this.getChildByModuleName("BoardCoverEdit"),
                    t = e.getBoardCoverData(),
                    n = this.getChildById("saveCover");
                n.showLoading();
                var i = this,
                    o = _.extend(t, {
                        board_id: this.extraData.boardId,
                        url: i.$(".in").attr("src")
                    }),
                    s = new P.Resource("BoardResource", o);
                s.call("update", {
                    success: function()
                    {
                        P.trackGAEvent("board_edit_cover", P.CONST.GA_ACTION_SUCCESS),
                        i.destroy(),
                        P.pubsub.publish(i.extraData.boardId, P.CONST.PUBSUB_TOPIC_BOARD_COVER_UPDATED, o);
                    },
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            },
            cancel: function()
            {
                P.trackGAEvent("board_edit_cover", P.CONST.GA_ACTION_CLICK_CANCEL),
                this.destroy();
            }
        });
        return e;
    }),
P.Module.define("BoardCreate", ["BoardEditBase"],
    function(e)
    {
        return e.extend({});
    }),
P.Module.define("BoardCreateRep", ["ModalTrigger"],
    function(e)
    {
        return e.extend({
            events: {
                click: "onClick"
            },
            onClick: function()
            {
                return this.showModal(),
                !1;
            },
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_BOARD_CREATED] = this.onBoardCreated,
                e[P.CONST.PUBSUB_TOPIC_BOARD_DELETED] = this.onBoardDeleted,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, e);
            },
            isSecretBoard: function(e)
            {
                return e.privacy && e.privacy === P.CONST.BOARD_PRIVACY_SECRET;
            },
            onBoardDeleted: function(e, t, n)
            {
                this.isSecretBoard(n) && this.options.submodule.options.num_secret_boards--;
            },
            onBoardCreated: function(e, t, n)
            {
                this.isSecretBoard(n) && this.options.submodule.options.num_secret_boards++;
            }
        });
    }),
P.Module.define("BoardEdit", ["BoardEditBase"],
    function(e)
    {
        return e.extend({
            initialize: function(t)
            {
                e.prototype.initialize.call(this, t),
                this.childListen(P.CONST.EVENT_INVITE_USER, this.onChildInviteUser),
                this.childListen(P.CONST.EVENT_INVITE_EMAIL, this.onChildInviteEmail),
                this.childListen(P.CONST.EVENT_CHANGE, this.onChildChange);
            },
            onContentReady: function()
            {
                e.prototype.onContentReady.call(this);
                var t = {};
                t[P.CONST.PUBSUB_TOPIC_BOARD_REMOVED_COLLABORATOR_SELF] = this.onBoardRemovedSelf,
                this.pubsubSubscribe(this.extraData.boardId, t);
            },
            onSubmitValidated: function()
            {
                var e = this;
                if (!this._showSecretBoardStatusChangeConfirmation)
                {
                    return e.saveBoard(),
                    void 0;
                }
                var t = {
                    name: "ConfirmDialog",
                    options: {
                        template: "make_public"
                    }
                };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM, e.saveBoard);
                    });
            },
            onButtonClick: function(t)
            {
                e.prototype.onButtonClick.call(this, t);
                var n = t.target;
                "deleteBoardButton" === n.id && this.onDeleteClick();
            },
            onChildChange: function(e)
            {
                if ("secretCheckbox" === e.target.id)
                {
                    var t = !e.target.isChecked();
                    this._showSecretBoardStatusChangeConfirmation = t ? !0 : !1;
                }
            },
            onChildInviteUser: function(e)
            {
                var t = this.getChildById("boardInviteForm");
                t.showLoading();
                var n = e.data.userId,
                    i = {
                        board_id: this.getBoardId(),
                        invited_user_id: n
                    },
                    o = e.data.pending,
                    s = o ? this.getChildById("boardPendingInvites") : this.getChildById("boardInvites"),
                    r = new P.Resource("BoardInviteResource", i);
                r.call("create", {
                    success: function()
                    {
                        P.trackGAEvent("collaborator_invite_user", P.CONST.GA_ACTION_SUCCESS),
                        s.addUserInvite(n),
                        t.clearTypeahead();
                    },
                    error: function(e)
                    {
                        P.showError(e.message),
                        P.trackGAEvent("collaborator_invite_user", P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            },
            onChildInviteEmail: function(e)
            {
                var t = this.getChildById("boardInviteForm");
                t.showLoading();
                var n = e.data.email,
                    i = {
                        board_id: this.getBoardId(),
                        email: n
                    },
                    o = new P.Resource("BoardEmailInviteResource", i);
                o.call("create", {
                    success: function()
                    {
                        P.trackGAEvent("collaborator_invite_email", P.CONST.GA_ACTION_SUCCESS);
                        var e = _.template(P.string("successInviteSentToEmail"));
                        t.clearTypeahead();
                        var i = $("<div class='alert'>" + e({
                            email: n
                        }) + "</div>");
                        i.hide().insertAfter(t.$el).fadeIn(function()
                        {
                            i.delay(5e3).fadeOut(function()
                            {
                                i.remove();
                            });
                        });
                    },
                    error: function(e)
                    {
                        P.showError(e.message),
                        P.trackGAEvent("collaborator_invite_email", P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            },
            onDeleteClick: function()
            {
                P.trackGAEvent("board_delete", P.CONST.GA_ACTION_OPEN_MODAL),
                this.showConfirmation();
            },
            onDeleteConfirm: function()
            {
                P.trackGAEvent("board_delete", P.CONST.GA_ACTION_CLICK_SUBMIT),
                this.deleteBoard();
            },
            showConfirmation: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "delete_board"
                        }
                    };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM, e.onDeleteConfirm);
                    });
            },
            deleteBoard: function()
            {
                var e = this,
                    t = this.getBoardId(),
                    n = this.getFieldValues(),
                    i = n.privacy,
                    o = new P.Resource("BoardResource", {
                        board_id: t
                    }),
                    s = function(e)
                    {
                        P.showError(e.message),
                        P.trackGAEvent("board_delete", P.CONST.GA_ACTION_ERROR);
                    },
                    r = function(n)
                    {
                        if (P.trackGAEvent("board_delete", P.CONST.GA_ACTION_SUCCESS), n)
                        {
                            var o = n.resource_response;
                            if (o && !o.error)
                            {
                                if (e.isInModal())
                                {
                                    P.pubsub.publish(t, P.CONST.PUBSUB_TOPIC_BOARD_DELETED),
                                    P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_BOARD_DELETED, {
                                        privacy: i
                                    }),
                                    e.destroy();
                                }
                                else
                                {
                                    var r = e.data.owner ? "/" + e.data.owner.username + "/" : "/";
                                    e.navigate(r);
                                }
                                return;
                            }
                        }
                        s(n);
                    };
                this.showLoading(),
                o.call("delete", {
                    success: r,
                    error: s,
                    complete: function()
                    {
                        e.hideLoading();
                    }
                });
            },
            onBoardRemovedSelf: function()
            {
                this.destroy();
            }
        });
    }),
P.Module.define("BoardEditBase", ["BoardCollaboratorInvitesBase"],
    function(e)
    {
        return e.extend({
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            setupForm: function()
            {
                this.$form = this.$("form");
                var e = this.extraData.errorMessages.name.required;
                this.form = new P.Form(this.$form, {
                    name: [P.Validator.Required({
                            message: e
                        }), P.Validator.Length({
                            max: P.CONST.MAX_CHARS_FOR_BOARD_TITLE
                        })],
                    description: [P.Validator.Length({
                        max: P.CONST.MAX_CHARS_FOR_BOARD_PIN_DESCRIPTION
                    })]
                }),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onContentReady: function()
            {
                this.setupForm();
            },
            onButtonClick: function(e)
            {
                var t = e.target;
                if (t)
                {
                    var n = this._getGACategory();
                    "submitButton" === t.id ? P.trackGAEvent(n, P.CONST.GA_ACTION_CLICK_SUBMIT) : "cancelButton" === t.id && P.trackGAEvent(n, P.CONST.GA_ACTION_CLICK_CANCEL);
                }
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.saveBoard();
            },
            getBoardId: function()
            {
                return this.data && this.data.id;
            },
            _getGACategory: function()
            {
                return this.getBoardId() ? "board_edit" : "board_create";
            },
            isMakePublic: function(e)
            {
                return this.data && "secret" === this.data.privacy && "public" === e;
            },
            getFieldValues: function()
            {
                var e = this.$("form"),
                    t = this.getChildById("boardCategory"),
                    n = {
                        name: e.find("[name=name]").val(),
                        category: t.getValue(),
                        description: e.find("[name=description]").val(),
                        privacy: e.find("[name=secret]:checked")[0] ? "secret" : "public",
                        collab_board_email: e.find("[name=email]:checked")[0] ? !0 : !1
                    };
                return n;
            },
            saveBoard: function()
            {
                var e = this.getChildById("submitButton"),
                    t = this.getFieldValues(),
                    n = this.getBoardId(),
                    i = _.clone(t);
                n && (i.board_id = n);
                var o = new P.Resource("BoardResource", i);
                e.showLoading(),
                o.call(n ? "update" : "create", {
                    success: _.bind(this.onSaveSuccess, this),
                    error: _.bind(this.onSaveError, this),
                    complete: function()
                    {
                        e.hideLoading();
                    }
                });
            },
            onSaveError: function(e)
            {
                P.trackGAEvent(this._getGACategory(), P.CONST.GA_ACTION_ERROR);
                var t = this.$(".formFooter"),
                    n = this.$(".inlineError");
                n.length ? n.empty() : n = $("<p></p>").addClass("inlineError"),
                n.text(e.message),
                n.insertBefore(t);
            },
            onSaveSuccess: function(e)
            {
                var t = this.getBoardId(),
                    n = !t;
                if (P.trackGAEvent(this._getGACategory(), P.CONST.GA_ACTION_SUCCESS), e)
                {
                    var i = e.resource_response;
                    if (i && !i.error && i.data)
                    {
                        var o = i.data;
                        return t ? (P.pubsub.publish(t, P.CONST.PUBSUB_TOPIC_BOARD_UPDATED, o), this.isMakePublic(o.privacy) && P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_BOARD_UPDATED, P.CONST.PUBSUB_MESSAGE_BOARD_SET_PUBLIC)) : P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_BOARD_CREATED, o),
                        !n && this.isInModal() ? this.destroy() : this.navigate(o.url),
                        void 0;
                    }
                }
            }
        });
    }),
P.Module.define("BoardFollowButton", ["ui.FollowButton"],
    function(e)
    {
        return e.extend({
            getResourceId: function()
            {
                return this.options.board_id;
            },
            getFollowResource: function()
            {
                return new P.Resource("BoardFollowResource", {
                    board_id: this.getResourceId()
                });
            },
            getFollowClass: function()
            {
                return this.options.follow_class;
            },
            onContentReady: function()
            {
                if (this.options.user_id)
                {
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_USER_FOLLOW] = this.onFollowUser,
                    e[P.CONST.PUBSUB_TOPIC_USER_UNFOLLOW] = this.onUnfollowUser,
                    this.pubsubSubscribe(this.options.user_id, e);
                }
                var t = {};
                t[P.CONST.PUBSUB_TOPIC_USER_FOLLOW] = this._onFollow,
                t[P.CONST.PUBSUB_TOPIC_USER_UNFOLLOW] = this._onUnfollow,
                this.pubsubSubscribe(this.getResourceId(), t);
            },
            _onFollow: function()
            {
                var e = {
                    board_id: this.getResourceId()
                };
                this.triggerEvent(P.CONST.EVENT_BOARD_FOLLOW, e, !0);
            },
            _onUnfollow: function()
            {
                var e = {
                    board_id: this.getResourceId()
                };
                this.triggerEvent(P.CONST.EVENT_BOARD_UNFOLLOW, e, !0),
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_BOARD_UNFOLLOW, !0);
            },
            onFollowUser: function()
            {
                this.setState(!0);
            },
            onUnfollowUser: function()
            {
                this.setState(!1);
            }
        });
    }),
P.Module.define("BoardHeader", [],
    function()
    {
        var e = "BoardInfoBar";
        return P.Module.extend({
            showEditModal: function()
            {
                var t = this.getChildByModuleName(e);
                return t.showEditModal();
            }
        });
    }),
P.Module.define("BoardInfoBar", [],
    function()
    {
        var e = "editButton";
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_BOARD_WRITE_ACCESS_UPDATED] = this.onWriteAccessChange,
                this.pubsubSubscribe(this.data.id, e);
            },
            onWriteAccessChange: function()
            {
                this.render();
            },
            showEditModal: function()
            {
                var t = this.getChildById(e);
                return t ? (t.showModal(), !0) : !1;
            }
        });
    }),
P.Module.define("BoardInvite", [],
    function()
    {
        var e = 5e3;
        return P.Module.extend({
            onContentReady: function()
            {
                this.declineButton = this.getChildById("declineButton"),
                this.removeButton = this.getChildById("removeButton"),
                this.acceptButton = this.getChildById("acceptButton"),
                this.approveButton = this.getChildById("approveButton"),
                this.declineButton && this.listen(this.declineButton, P.CONST.EVENT_BUTTON_CLICK, this.onClickDecline),
                this.removeButton && this.listen(this.removeButton, P.CONST.EVENT_BUTTON_CLICK, this.onClickRemove),
                this.acceptButton && this.listen(this.acceptButton, P.CONST.EVENT_BUTTON_CLICK, this.onClickAccept),
                this.approveButton && this.listen(this.approveButton, P.CONST.EVENT_BUTTON_CLICK, this.onClickApprove);
            },
            getInvitedUserId: function()
            {
                return this.extraData.invitedUserId;
            },
            getRemoveResource: function()
            {
                var e = this.extraData.accepted,
                    t = e ? "BoardCollaboratorResource" : "BoardInviteResource",
                    n = new P.Resource(t, this.resource.copyOptions(!0));
                return n;
            },
            getCurrentUserIsInvitedUser: function()
            {
                return this.extraData.currentUserIsInvitedUser;
            },
            getInvitedUserFullName: function()
            {
                return this.extraData.invitedUserFullName;
            },
            getConfirmBoardInvite: function()
            {
                return "boardEdit" === this.options.view_type;
            },
            onClickRemove: function()
            {
                this.getConfirmBoardInvite() ? this.confirmDeleteBoardInvite() : this.deleteBoardInvite();
            },
            confirmDeleteBoardInvite: function()
            {
                var e = this.getCurrentUserIsInvitedUser(),
                    t = this.getInvitedUserFullName(),
                    n = this,
                    i = {
                        name: "ConfirmDialog",
                        options: {
                            template: "delete_board_invite",
                            current_user_is_invited_user: e,
                            invited_user_full_name: t
                        }
                    };
                P.loadModule(i,
                    function(e)
                    {
                        n.showInModal(e),
                        n.listen(e, P.CONST.EVENT_CONFIRM, n.deleteBoardInvite);
                    });
            },
            deleteBoardInvite: function()
            {
                var e, t = this.getCurrentUserIsInvitedUser(),
                    n = this;
                e = t ? "collaborator_decline_invite" : "collaborator_delete_invite",
                P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK),
                this.removeButton.showLoading();
                var i = this.getRemoveResource();
                i.call("delete", {
                    success: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_SUCCESS),
                        n.fadeOut(function()
                        {
                            n.destroy();
                        });
                        var i = n.data.board.id;
                        t && (P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_BOARD_REMOVED_COLLABORATOR_SELF), P.pubsub.publish(i, P.CONST.PUBSUB_TOPIC_BOARD_REMOVED_COLLABORATOR_SELF));
                    },
                    error: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        n.removeButton.hideLoading();
                    }
                });
            },
            onClickAccept: function()
            {
                var t = "collaborator_invite_accept";
                P.trackGAEvent(t, P.CONST.GA_ACTION_CLICK);
                var n = this;
                this.acceptButton.showLoading();
                var i = this.resource.copy(!0);
                i.call("update", {
                    success: function()
                    {
                        P.trackGAEvent(t, P.CONST.GA_ACTION_SUCCESS);
                        var i = n.$(".pending"),
                            o = n.$(".success"),
                            s = n.data.board.id;
                        P.pubsub.publish(s, P.CONST.PUBSUB_TOPIC_BOARD_WRITE_ACCESS_UPDATED),
                        i.fadeOut(function()
                        {
                            o.fadeIn(function()
                            {
                                o.delay(e).fadeOut(function()
                                {
                                    n.destroy();
                                });
                            });
                        });
                    },
                    error: function()
                    {
                        P.trackGAEvent(t, P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        n.acceptButton.hideLoading();
                    }
                });
            },
            onClickApprove: function()
            {
                var e = "collaborator_approve_invite",
                    t = new P.Resource("BoardInviteResource", this.resource.copyOptions(!0));
                this.approveButton.showLoading();
                var n = this;
                t.call("update", {
                    success: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_SUCCESS),
                        n.fadeOut(function()
                        {
                            n.destroy();
                        });
                        var t = n.data.board.id;
                        P.pubsub.publish(t, P.CONST.PUBSUB_TOPIC_BOARD_APPROVED_COLLABORATOR_INVITE, {
                            userId: n.getInvitedUserId()
                        });
                    },
                    error: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        n.approveButton.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("BoardInviteForm", [],
    function()
    {
        return P.Module.extend({
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_ITEM_SELECTED, this.onChildItemSelected),
                this.childListen("enterPressed", this.onChildEnterPressed),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onClickInviteButton);
            },
            onChildItemSelected: function(e)
            {
                P.trackGAEvent("collaborator_invite_user", P.CONST.GA_ACTION_SELECT_SUBMIT);
                var t = e.data.item,
                    n = t.get("id");
                this.inviteUser(n),
                e.stopPropagation();
            },
            onChildEnterPressed: function(e)
            {
                P.trackGAEvent("collaborator_invite_email", P.CONST.GA_ACTION_ENTER_SUBMIT),
                this.submit(),
                e.stopPropagation();
            },
            onClickInviteButton: function(e)
            {
                P.trackGAEvent("collaborator_invite_email", P.CONST.GA_ACTION_CLICK_SUBMIT),
                this.submit(),
                e.stopPropagation();
            },
            submit: function()
            {
                var e = this.getChildById("typeaheadField"),
                    t = e.getValue(),
                    n = e.getField(),
                    i = this;
                if (this.options.email_supported)
                {
                    var o = new P.Validator(n, [P.Validator.Length({
                        min: 1
                    }), P.Validator.Email()]);
                    o.validate(function(e)
                    {
                        e.errors.length > 0 ? P.log(e.errors) : i.inviteEmail(t);
                    });
                }
                return !1;
            },
            setTypeaheadFieldValue: function(e)
            {
                var t = this.getChildById("typeaheadField");
                t.setValue(e);
            },
            clearTypeahead: function()
            {
                var e = this.getChildById("typeaheadField");
                e.clear();
            },
            inviteEmail: function(e)
            {
                this.triggerEvent(P.CONST.EVENT_INVITE_EMAIL, {
                        email: e
                    },
                    !0);
            },
            inviteUser: function(e)
            {
                this.triggerEvent(P.CONST.EVENT_INVITE_USER, {
                        userId: e,
                        pending: this.options.pending
                    },
                    !0);
            }
        });
    }),
P.Module.define("BoardInvites", ["BoardInvite"],
    function(e)
    {
        return P.Module.extend({
            onContentReady: function()
            {
                if (!this.options.pending)
                {
                    var e = this.resource.options.board_id,
                        t = {};
                    t[P.CONST.PUBSUB_TOPIC_BOARD_APPROVED_COLLABORATOR_INVITE] = this.onApprovedCollaboratorInvite,
                    this.pubsubSubscribe(e, t);
                }
            },
            _prependUserToTop: function(t)
            {
                var n = new e({
                    resource: {
                        name: "BoardInviteResource",
                        options: {
                            board_id: this.resource.options.board_id,
                            invited_user_id: t,
                            field_set_key: "boardEdit"
                        }
                    }
                }),
                    i = this.getChildByModuleName("PagedGrid");
                n.render(function()
                {
                    i.prependChildItem(n);
                });
            },
            addUserInvite: function(e)
            {
                this._prependUserToTop(e);
            },
            onApprovedCollaboratorInvite: function(e, t, n)
            {
                this.addUserInvite(n.userId);
            }
        });
    }),
P.Module.define("BoardPage", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                if (this.data.id)
                {
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_BOARD_UPDATED] = this.onBoardUpdated,
                    e[P.CONST.PUBSUB_TOPIC_BOARD_DELETED] = this.onBoardDeleted,
                    e[P.CONST.PUBSUB_TOPIC_BOARD_REMOVED_COLLABORATOR_SELF] = this.onBoardRemovedSelf,
                    this.pubsubSubscribe(this.data.id, e);
                }
                this.childListen("pinUpdated", this.onChildPinUpdated),
                this.options.show_edit && (this.extraData.canEdit && this.showEditModal(), delete this.options.show_edit);
            },
            onBoardUpdated: function(e, t, n)
            {
                n.url !== this.data.url && this.inDom ? (this.data.url = n.url, this.navigate(n.url)) : this.headerDataChanged(n) && this.renderHeader();
            },
            headerDataChanged: function(e)
            {
                var t = _.pick(this.data, "privacy", "description"),
                    n = _.pick(e, "privacy", "description");
                return !_.isEqual(t, n);
            },
            onBoardDeleted: function()
            {
                this.inDom && this.navigateToUserPage();
            },
            navigateToUserPage: function()
            {
                var e = this.extraData && this.extraData.currentUsername,
                    t = "/",
                    n = e ? t + e + "/" : t;
                this.navigate(n);
            },
            getHeader: function()
            {
                return this.getChildById("boardHeader");
            },
            renderHeader: function()
            {
                var e = this.getHeader();
                e.render();
            },
            showEditModal: function()
            {
                var e = this.getHeader();
                return e.showEditModal();
            },
            onChildPinUpdated: function(e)
            {
                var t = e.data.board.id,
                    n = e.target;
                t !== this.data.id && n.destroy();
            },
            onBoardRemovedSelf: function()
            {
                this.data.privacy === P.CONST.BOARD_PRIVACY_SECRET && this.inDom ? this.navigateToUserPage() : this.renderHeader();
            }
        });
    }),
P.Module.define("BoardPicker", [],
    function()
    {
        var e = "data-id",
            t = "data-privacy",
            n = "data-collaborative",
            i = "active",
            o = "visible";
        return P.Module.extend({
            events: {
                "click .boardPickerOuter": "onOuterClick",
                "click .boardPickerItem": "onItemClick",
                "keydown .createBoardName": "onCreateBoardKeydown"
            },
            onCreateBoardKeydown: function(e)
            {
                var t = P.keyCode;
                return e.keyCode === t.ENTER ? (this.onCreateBoard(), !1) : void 0;
            },
            onButtonClick: function(e)
            {
                var t = e.target;
                t && "createBoard" === t.id && this.onCreateBoard();
            },
            initialize: function()
            {
                this.$boardOuter = null,
                this.$boardMenuWrapper = null,
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onItemClick: function(i)
            {
                var o = $(i.target),
                    s = o.attr(e);
                if (!s)
                {
                    return i.stopImmediatePropagation(),
                    void 0;
                }
                this._selectedBoardId = s;
                var r = o.text(),
                    a = o.attr(t),
                    l = !!o.attr(n);
                this.setSelectedBoard(s, r, a, l),
                this.triggerEvent(P.CONST.EVENT_BOARD_SELECTED, {
                        privacy: a
                    },
                    !0),
                this.closeMenu();
            },
            onCreateBoard: function()
            {
                function e(e)
                {
                    P.showError(e.message);
                }
                function t(t)
                {
                    if (t)
                    {
                        var n = t.resource_response;
                        if (n && !n.error && n.data && n.data.url)
                        {
                            return s.options.default_board_id = n.data.id,
                            s.render(),
                            s.triggerEvent(P.CONST.EVENT_BOARD_SELECTED, null, !0),
                            void 0;
                        }
                    }
                    e();
                }
                var n = this.getChildById("createBoard"),
                    i = this.$(".createBoardName").val(),
                    o = new P.Resource("BoardResource", {
                        name: i
                    }),
                    s = this;
                n.showLoading(),
                o.call("create", {
                    success: t,
                    error: e,
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            },
            getSelectedBoardName: function()
            {
                return this.$(".currentBoardName").text();
            },
            getPrivacy: function()
            {
                return this.$(".currentBoard").attr(t);
            },
            getCollaborative: function()
            {
                return !!this.$(".currentBoard").attr(n);
            },
            setSelectedBoardAttributes: function(e, i)
            {
                var o = $(".currentBoard", this.$boardOuter);
                o.attr(t, e),
                o.attr(n, i);
            },
            setSelectedBoardIcons: function(e, t)
            {
                var n = $(".currentBoard", this.$boardOuter),
                    i = n.find(".secretIcon"),
                    o = n.find(".collaborativeIcon");
                i.toggleClass("hidden", !e),
                o.toggleClass("hidden", !t);
            },
            setSelectedBoard: function(t, n, i, o)
            {
                var s = this,
                    r = $(".currentBoard", this.$boardOuter),
                    a = o,
                    l = "secret" === i;
                this._selectedBoardId = t,
                this.setSelectedBoardAttributes(i, o),
                this.setSelectedBoardIcons(l, a),
                r.attr(e, s._selectedBoardId),
                $(".currentBoardName", r).text(n);
            },
            onContentReady: function()
            {
                this.$boardOuter = this.$(".boardPickerOuter"),
                this.$boardMenuWrapper = this.$(".boardPickerInnerWrapper"),
                this.$(".createBoardName").placeholder(),
                this._selectedBoardId = this.$boardOuter.attr(e);
            },
            onOuterClick: function(t)
            {
                this.options.disabled || (this._selectedBoardId = $(t.target).attr(e), this.openMenu());
            },
            openMenu: function()
            {
                var t = this,
                    n = $("<div></div>").addClass("boardPickerMask");
                this.$el.append(n);
                var s = this._selectedBoardId || this.$(".currentBoard").attr(e),
                    r = this.$(".boardPickerInner").find("[" + e + "=" + s + "]");
                r.addClass(i),
                n.on("click.boardpicker",
                    function(e)
                    {
                        t.closeMenu(),
                        e.stopPropagation(),
                        e.stopImmediatePropagation();
                    }),
                this.$boardMenuWrapper.addClass(o);
            },
            closeMenu: function()
            {
                var e = $(".boardPickerMask");
                e.off("click.boardpicker"),
                e.detach(),
                this.$(".boardPickerInner").find("." + i).removeClass(i),
                this.$boardMenuWrapper.removeClass(o);
            },
            getSelectedBoardId: function()
            {
                return $(".currentBoard", this.$boardOuter).attr(e);
            }
        });
    }),
P.Module.define("BoardRecFeedHomePage", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                var e = this.getChildById("grid"),
                    t = "none";
                e && !e.hasItems() && (e.remove(), t = "block"),
                this.$(".noResults").css("display", t);
            }
        });
    }),
P.Module.define("BoardRecommendationsModule", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.destroyIfEmpty();
            },
            isEmpty: function()
            {
                if (!this.contentReady)
                {
                    return !1;
                }
                var e = this.getChildById("relatedBoardsFeed");
                return !e || !e.hasItems();
            }
        });
    }),
P.Module.define("BoardsToFollow", ["Board", "Dropdown"],
    function(e)
    {
        var t = 4,
            n = "follow_view";
        return P.Module.extend({
            events: {},
            boardsUsed: [],
            boardsUnused: [],
            boardsToReplace: [],
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_DISMISS, this.onChildDismiss),
                this.childListen(P.CONST.EVENT_BOARD_FOLLOW, this.onChildBoardFollow);
            },
            onContentReady: function()
            {
                var e = this;
                this.boardsUnused = this.extraData.boardsUnused,
                e.requestMoreBoardsIfNeeded(),
                e.replaceBoardsWithUnused();
            },
            onChildDismiss: function(e)
            {
                var t = e.target;
                this.dismissBoard(t);
            },
            onChildBoardFollow: function(e)
            {
                var t = e.target.parent,
                    i = this;
                t.options.view_type === n && window.setTimeout(function()
                {
                    i.dismissBoard(t);
                },
                    500);
            },
            requestMoreBoardsIfNeeded: function()
            {
                var e = this;
                e.boardsUnused.length > t || this.resource.xhr || this.resource.call("get", {
                    success: function(t)
                    {
                        var n = t.resource_response.data;
                        e.boardsUnused = e.boardsUnused.concat(n),
                        e.replaceBoardsWithUnused();
                    }
                });
            },
            dismissBoard: function(e)
            {
                if (e && !e.dismissing)
                {
                    var t = this;
                    e.dismissing = !0,
                    t.requestMoreBoardsIfNeeded(),
                    e.fadeOut(function()
                    {
                        t.replaceBoard(e);
                    });
                }
            },
            getBoard: function(t)
            {
                var i = new e({
                    options: {
                        show_board_context: !0,
                        view_type: n,
                        size: "small"
                    },
                    resource: {
                        name: "BoardResource",
                        options: {
                            board_id: t.id
                        }
                    },
                    data: t
                });
                return i;
            },
            hideBoard: function(e)
            {
                e && (e._dropDown && e._dropDown.hide(), e.destroy());
            },
            replaceBoardsWithUnused: function()
            {
                for (var e = this; e.boardsToReplace.length && e.boardIdsUnused.length;)
                {
                    var t = e.boardsToReplace.shift();
                    e.replaceBoard(t);
                }
            },
            replaceBoard: function(e)
            {
                var t = this,
                    n = this.boardsUnused.pop();
                if (n)
                {
                    var i = t.getBoard(n);
                    i.render(function()
                    {
                        t.getChildByModuleName("List").appendChild(i),
                        t.hideBoard(e),
                        i.show(),
                        i.fadeIn();
                    },
                        function()
                        {
                            t.hideBoard(e),
                            t.replaceBoard(i);
                        }),
                    this.boardsUsed.push(n);
                }
            }
        });
    }),
P.Module.define("BusinessAccountConvert", [],
    function()
    {
        return P.Module.extend({
            events: {
                "keyup .aboutText": "onAboutTextKeyup"
            },
            onContentReady: function()
            {
                var e = {
                    contact_name: [P.Validator.Required()],
                    email: [P.Validator.Email(), P.Validator.Required()],
                    account_type: [P.Validator.Required()],
                    business_name: [P.Validator.Required()],
                    username: [P.Validator.Required()],
                    about: [P.Validator.Length({
                        max: P.CONST.MAX_CHARS_FOR_USER_DESCRIPTION
                    })],
                    accept_terms: [P.Validator.Required()]
                },
                    t = {
                        prevalidate: !0
                    };
                this.$aboutCounter = $(".aboutCounter"),
                this.$(".aboutText").keyup(),
                this.$form = this.$("form"),
                this.form = new P.Form(this.$form, e, t),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.save();
            },
            onAboutTextKeyup: function(e)
            {
                var t = e.target.value.replace(/\{.*\}/g, "").length,
                    n = P.CONST.MAX_CHARS_FOR_USER_DESCRIPTION,
                    i = t < n ? n - t : 0;
                this.$aboutCounter.text(i);
            },
            save: function()
            {
                var e = this,
                    t = this.$form.serializeArray(),
                    n = {};
                _.each(t,
                    function(e)
                    {
                        n[e.name] = "on" === e.value ? !0 : e.value;
                    });
                var i = this.getChildById("submitButton"),
                    o = new P.Resource("PartnerResource", n),
                    s = function(t)
                    {
                        t && !t.resource_response.error && e.navigate("/business/getstarted/");
                    };
                i.showLoading(),
                o.call("update", {
                    success: s,
                    complete: function()
                    {
                        i.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("BusinessAccountCreate", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                if (P.currentUser.isAuthenticated())
                {
                    var e = "/business/convert/";
                    return P.currentUser.attributes.is_partner && (e = "/business/getstarted/"),
                    this.navigate(e),
                    void 0;
                }
            }
        });
    }),
P.Module.define("BusinessGetStarted", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .partnerCreateBoard": "createBoard"
            },
            createBoard: function()
            {
                return P.trackGAEvent("board_create", P.CONST.GA_ACTION_OPEN_MODAL),
                this.showBoardCreateModal(),
                !1;
            },
            showBoardCreateModal: function()
            {
                var e = this;
                P.Loader.require(["BoardCreate"],
                    function(t)
                    {
                        var n = new t({
                            options: {}
                        });
                        e.showInModal(n);
                    });
            }
        });
    }),
P.Module.define("BusinessGetStartedCards", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .dismiss": "onDismissClick"
            },
            onDismissClick: function(e)
            {
                var t = $(e.target),
                    n = t.parents(".getStartedCard"),
                    i = n.data("card-name"),
                    o = new P.Resource("PartnerCardResource", {
                        card_name: i
                    });
                o.call("delete", {}),
                n.remove();
            }
        });
    }),
P.Module.define("BusinessGetStartedHeader", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("Button", [],
    function()
    {
        var e = "disabled",
            t = "disabled";
        return P.Module.extend({
            events: {
                click: "onClick"
            },
            onClick: function(e)
            {
                return this.isDisabled() ? (e.preventDefault(), !1) : (this.triggerEvent(P.CONST.EVENT_BUTTON_CLICK, null, !0), void 0);
            },
            isDisabled: function()
            {
                return this.$el.is(":disabled");
            },
            disable: function()
            {
                this.$el.attr(e, !0).addClass(t);
            },
            enable: function()
            {
                this.$el.removeAttr(e).removeClass(t);
            },
            setStyles: function(e)
            {
                var t = this.$el;
                _.each(e,
                    function(e, n)
                    {
                        t.toggleClass(n, e);
                    });
            },
            setDisabled: function(e)
            {
                var t = "disabled",
                    n = this.$el;
                return e ? n.removeAttr(t) : n.attr(t, !0);
            },
            getLoadingSpinnerOptions: function()
            {
                return {
                    size: P.Spinner.Size.SMALL
                };
            },
            showLoading: function()
            {
                this.disable(),
                this.options.borderless || P.Module.prototype.showLoading.call(this);
            },
            hideLoading: function()
            {
                this.enable(),
                this.options.borderless || P.Module.prototype.hideLoading.call(this);
            },
            isCancelButton: function()
            {
                return this.options.cancelButton;
            },
            isActive: function()
            {
                return this.$el.hasClass("active");
            }
        });
    }),
P.Module.define("CategoriesMenu", [],
    function()
    {
        var e = "selected",
            t = P.Module.extend({
                getItemByCategory: function(e)
                {
                    return this.$("a[data-category=" + e + "]");
                },
                onCategoryUpdated: function(t, n, i)
                {
                    if (this.$("a").removeClass(e), i)
                    {
                        var o = this.getItemByCategory(i);
                        o.length ? (o.addClass(e), this.waitingMessage = null) : this.waitingMessage = i;
                    }
                },
                onContentReady: function()
                {
                    var t = {};
                    t[P.CONST.PUBSUB_TOPIC_CURRENT_CATEGORY] = this.onCategoryUpdated,
                    this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_SITE, t),
                    this.waitingMessage && this.getItemByCategory(this.waitingMessage).addClass(e);
                }
            });
        return t;
    }),
P.Module.define("CategoriesSelect", [],
    function()
    {
        return P.Module.extend({
            getValue: function()
            {
                return $.trim(this.$("option:selected").val());
            }
        });
    }),
P.Module.define("Close", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                window.close();
            }
        });
    }),
P.Module.define("Closeup", ["PinActionBar", "CloseupContent", "CloseupSidebar", "CloseupBottom"],
    function(e, t, n, i)
    {
        var o = "actions",
            s = "content",
            r = "sidebar",
            a = "bottom",
            l = ".closeupActionBarContainer",
            u = 736,
            c = 57,
            d = 40,
            h = 14,
            p = 1e3,
            f = "visible";
        return P.Module.extend({
            events: {
                click: "_onClick",
                "click button.close": "onCloseButtonClick"
            },
            getOwnedScrollables: function()
            {
                return this.options.can_close ? this.$el : $();
            },
            initialize: function()
            {
                this.closeDiv = $('<button class="Button borderless close"><em></em>&nbsp;</button>');
            },
            onKeyup: function(e)
            {
                this.options.can_close && e.keyCode === P.keyCode.ESCAPE && this._close();
            },
            _close: function()
            {
                this.triggerEvent("close", this, !0);
            },
            _unsticky: function()
            {
                this._actionBar && this._actionBar.unsticky();
            },
            _updateSticky: function()
            {
                if (this.parent && this.inDom && this._actionBar)
                {
                    var e = this.$(".PaddedPin"),
                        t = this.getScrollableElement(),
                        n = 0;
                    this.options.can_close || (n = $(".headerBackground").height()),
                    this._actionBar.updateSticky({
                        $boundTo: e,
                        $scrollable: t,
                        headerHeight: n
                    });
                }
            },
            resetCloseButton: function()
            {
                this.$close.removeClass(f);
            },
            onAddedToDom: function()
            {
                var e = this;
                this.options.can_close && $("body").on("keyup.closeup",
                    function(t)
                    {
                        e.onKeyup(t);
                    }),
                this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate);
                var t = P.scrollbarWidth();
                this.$close || (this.$close = this.$(".close")),
                this.$close.css("right", t + h + "px").addClass(f);
            },
            _positionActionBar: function()
            {
                this._actionBar && this.inDom && this.contentReady && this._updateSticky();
            },
            onContentReady: function()
            {
                this._actionBar = this.getChildById(o),
                this.options.show_repin ? (this.showRepinModal(), delete this.options.show_repin) : this.options.show_edit && (this.extraData.canEdit && this.showEditModal(), delete this.options.show_edit),
                this._positionActionBar();
            },
            onChildRemoved: function(e)
            {
                "CloseupContent" === e.className && (this.options.can_close ? this._close() : (this.destroy(), this.navigate("/")));
            },
            _removeTransitionImage: function()
            {
                this.transitionPinImage && (this.transitionPinImage.remove(), this.transitionPinImage = null);
            },
            onRemovedFromDom: function()
            {
                this._actionBar && this._actionBar.removeDropdowns(),
                this._unsticky(),
                this.options.can_close && $("body").off("keyup.closeup"),
                this._removeListeners();
            },
            render: function(u)
            {
                if (!this.options.can_close)
                {
                    return P.Module.prototype.render.call(this, u);
                }
                this.$el.empty().addClass("canClose"),
                this.$el.append(this.closeDiv),
                this.$el.append('<div class="closeupActionBarContainer"></div><div class="closeupContainer"></div><div class="closeupBottom"></div>');
                var c = !!this.transitionPinImage;
                c && (this.$el.append(this.transitionPinImage), u());
                var d = this,
                    h = this.resource.copy(),
                    p = this.resource.options.id,
                    f = this.resource.copy();
                f.options.view_type = "detailed";
                var m = new t({
                    id: s,
                    resource: f
                }),
                    g = d.$(l),
                    v = new e({
                        id: o,
                        options: {
                            pin_id: p
                        },
                        resource: h
                    });
                v.render(),
                this._actionBar = v,
                this.insertChild(v, g);
                var C = this.$(".closeupContainer");
                m.render(function()
                {
                    if (d.insertChild(m, C), c)
                    {
                        var e = m.getPin(),
                            t = e.getPinMedia(),
                            n = t.attr("src");
                        t.load(_.bind(d._removeTransitionImage, d)),
                        t.error(_.bind(d._removeTransitionImage, d)),
                        t.attr("src", n),
                        t[0] && t[0].complete && d._removeTransitionImage();
                    }
                    d.contentReady = !0,
                    d.onContentReady(),
                    c || u();
                    var o = new i({
                        id: a,
                        options: {
                            pin_id: d.resource.options.id
                        }
                    }),
                        s = d.$(".closeupBottom");
                    o.render(function()
                    {
                        d.insertChild(o, s);
                    });
                });
                var y = this.resource.copy();
                y.options.view_type = "closeup_sidebar";
                var T = new n({
                    id: r,
                    resource: y
                });
                T.render(function()
                {
                    d.insertChild(T, C);
                });
            },
            setCloseupBottomMinHeight: function()
            {
                var e = this.$(".closeupContainer").height(),
                    t = this.getScrollableElement().scrollTop(),
                    n = this.getChildById(a),
                    i = P.Viewport.height,
                    o = t + i - e;
                n.$el.css("min-height", o);
            },
            removeCloseupBottomMinHeight: function()
            {
                var e = this.getChildById(a);
                e.$el.css("min-height", "");
            },
            showRepinModal: function()
            {
                this._actionBar && this._actionBar.showRepinModal();
            },
            showEditModal: function()
            {
                var e = this.getChildById(s);
                return e.showEditModal();
            },
            setAsMainModule: function(t, n, i, u)
            {
                var c = this,
                    d = this.getChildById(s),
                    h = this.getChildById(r),
                    p = this.getChildById(a),
                    f = n.options.id;
                if (!d || !h || !p)
                {
                    return P.Module.prototype.setAsMainModule.apply(this, arguments);
                }
                if (this._removeTransitionImage(), t.can_close ? 0 === this.closeDiv.parent().length && (this.$el.prepend(this.closeDiv), this.$el.addClass("canClose")) : this.closeDiv.parent().length > 0 && (this.closeDiv.remove(), this.$el.removeClass("canClose")), this.options.can_close = t.can_close, this.hasSameOptions(t, n) && this.contentReady && !this._forceRefresh(i))
                {
                    return u(),
                    void 0;
                }
                this.setOptions(t),
                this.setResource(n),
                i.evt && i.evt.currentTarget && "Closeup" === i.evt.currentTarget.className || d.empty();
                var m = {
                    name: n.name,
                    options: _.extend({},
                        n.options)
                },
                    g = this.resource.copy(),
                    v = new e({
                        id: o,
                        options: {
                            pin_id: f
                        },
                        resource: g
                    });
                m.options.view_type = "detailed",
                d.setResource(m),
                this.setCloseupBottomMinHeight(),
                v.render(),
                d.render(function()
                {
                    var e = c.$(l);
                    c.insertChild(v, e),
                    c._actionBar && c._actionBar.destroy(),
                    c._actionBar = v,
                    c._positionActionBar(),
                    p.setOptions({
                        pin_id: f
                    }),
                    p.render(function()
                    {
                        c.removeCloseupBottomMinHeight();
                    }),
                    h.updateDomain(d.data.domain);
                }),
                u();
            },
            onChildNavigate: function(e)
            {
                if (P.log("Closeup got navigate event from child", e.target, "for url:", e.data.url), !P.isOffsiteUrl(e.data.url))
                {
                    var t = this.getChildById(r);
                    return t === e.currentTarget && "Pin" === e.target.className && (e.data.handled = !0),
                    !1;
                }
            },
            onCloseButtonClick: function()
            {
                return this._close(),
                this.resetCloseButton(),
                !1;
            },
            _onClick: function(e)
            {
                if (this.options.can_close)
                {
                    var t = e.target;
                    (t && (t === this.$el[0] || t === this.$(".closeupContainer")[0]) || t === this.$(".closeupBottom")[0]) && (e.stopPropagation(), this._close());
                }
            },
            performTransition: function(e, t)
            {
                var n = this,
                    i = e.evt && e.evt.target || null,
                    o = e.evt && e.evt.currentTarget || null;
                i && "Pin" === i.className && "summary" === i._getViewType() && "Closeup" !== o.className && (this.transitionPinImage = this._getTransitionPinImage(i)),
                n.render(function()
                {
                    t();
                });
            },
            _getTransitionPinImage: function(e)
            {
                var t = e.getPinMedia();
                if (!t)
                {
                    return null;
                }
                var n = t.clone(),
                    i = e.data.link;
                i || (e.data.images.orig ? i = e.data.images.orig.url : e.data.images.originals && (i = e.data.images.originals.url));
                var o = $("<a class='transitionImage' href='" + i + "'></a>").append(n);
                n[0].onload = null;
                var s, r = e.getDetailedImageDimensions(),
                    a = r.height,
                    l = r.width;
                if (l < u)
                {
                    var f = Math.round((u - l) / 2);
                    s = f < d ? f + c : d + c;
                }
                else
                {
                    s = c;
                }
                var m = 2 * h,
                    g = (P.Viewport.width - p + h) / 2,
                    v = (u - l) / 2;
                return o.css({
                    height: a,
                    padding: s + "px " + v + "px " + (s - c) + "px",
                    left: g,
                    top: m
                }),
                n.css({
                    height: a,
                    width: l
                }),
                o;
            },
            getPin: function()
            {
                return this.getChildById(s).getPin();
            }
        });
    }),
P.Module.define("CloseupBottom", [],
    function()
    {
        var e = "relatedPins",
            t = "relatedBoards";
        return P.Module.extend({
            events: {},
            onChildRendered: function(n)
            {
                var i, o, s = n.id === e,
                    r = n.id === t;
                if (s && (i = n.getChildByModuleName("Grid"), o = this.$(".relatedPinsWrapper")), r && (i = n.getChildByModuleName("PagedGrid"), o = this.$(".relatedBoardsWrapper")), i && o.length)
                {
                    var a = i.hasItems(),
                        l = a ? "visible" : "hidden";
                    o.css("visibility", l);
                }
            }
        });
    }),
P.Module.define("CloseupContent", [],
    function()
    {
        return P.Module.extend({
            events: {},
            getPin: function()
            {
                return this.getChildById("pin");
            },
            showEditModal: function()
            {
                var e = this.getPin();
                return e.showEditModal();
            },
            onContentReady: function()
            {
                if (this.data.id)
                {
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_PIN_DELETED] = this.onPinDeleted,
                    this.pubsubSubscribe(this.data.id, e);
                }
            },
            onPinDeleted: function()
            {
                this.destroy();
            }
        });
    }),
P.Module.define("CloseupRelatedBoards", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.destroyIfEmpty();
            },
            isEmpty: function()
            {
                if (!this.contentReady)
                {
                    return !1;
                }
                var e = this.getChildById("relatedBoardsFeed");
                return !e || !e.hasItems();
            }
        });
    }),
P.Module.define("CloseupRelatedPins", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.destroyIfEmpty();
            },
            isEmpty: function()
            {
                if (!this.contentReady)
                {
                    return !1;
                }
                var e = this.getChildById("relatedPinsFeed");
                return !e || !e.hasItems();
            }
        });
    }),
P.Module.define("CloseupSidebar", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                if (this.data.id)
                {
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_PIN_UPDATED] = this.onPinUpdated,
                    this.pubsubSubscribe(this.data.id, e);
                }
                var t = this.getChildByModuleName("Board");
                t.positionBoardPinsGrid();
            },
            onPinUpdated: function()
            {
                this.render();
            },
            updateDomain: function(e)
            {
                var t = this.getChildById("domain");
                if (!e)
                {
                    return t && (t.destroy(), this.$(".domainContainerTitle").hide()),
                    void 0;
                }
                if (!t && e)
                {
                    var n = {
                        name: "Domain",
                        id: "domain",
                        resource: {
                            name: "DomainResource",
                            options: {
                                domain: e
                            }
                        }
                    },
                        i = this;
                    return P.loadModule(n,
                        function(e)
                        {
                            e.render(function()
                            {
                                i.$(".domainContainerTitle").show(),
                                i.insertChild(e, i.$("#domainContainer"));
                            });
                        }),
                    void 0;
                }
                t.resource.set("domain", e),
                t.render(function()
                {
                    t.fadeIn();
                });
            }
        });
    }),
P.Module.define("ConfirmDialog", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .cancelButton": "close",
                "click .confirm": "confirm",
                "change #confirmCheckbox": "onConfirmCheckboxChange"
            },
            render: function(e)
            {
                var t = this,
                    n = function()
                    {
                        t.triggerEvent("rendered", t),
                        e && e();
                    };
                return this.options.message ? (this.empty(), this.$el.append('<form class="standardForm"><h1>' + P.string("errorTitle") + "</h1>" + '<p class="body">' + this.options.message + "</p>" + '<div class="formFooter">' + '<div class="formFooterButtons">' + '<button class="Button confirm btn primary rounded">' + P.string("ok") + "</button>" + "</div>" + "</div>" + "</form>"), n(), void 0) : P.Module.prototype.render.call(this, n);
            },
            onConfirmCheckboxChange: function()
            {
                this.$("#confirmCheckbox").is(":checked") ? this.$(".confirm").removeAttr("disabled") : this.$(".confirm").attr("disabled", "disabled");
            },
            close: function()
            {
                return this.triggerEvent(P.CONST.EVENT_CLOSE, this),
                this.destroy(),
                !1;
            },
            open: function()
            {
                this.triggerEvent(P.CONST.EVENT_OPEN, this);
            },
            confirm: function()
            {
                return this.showLoading(!0),
                this.triggerEvent(P.CONST.EVENT_CONFIRM, this),
                this.destroy(),
                !1;
            }
        });
    }),
P.Module.define("Consumer", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("ConsumerEditDialog", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {
                    name: [P.Validator.Required()],
                    description: [P.Validator.Required()]
                };
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form"), e),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.updateConsumer();
            },
            getFormData: function()
            {
                var e = this.$("form").serializeArray(),
                    t = {};
                return _.each(e,
                    function(e)
                    {
                        t[e.name] = e.value;
                    }),
                t;
            },
            getSaveResource: function(e)
            {
                return new P.Resource("ConsumerResource", e);
            },
            updateConsumer: function()
            {
                var e = this.getFormData();
                e.id = this.data.id;
                var t = this.getChildById("submitButton"),
                    n = this;
                t.showLoading();
                var i = this.getSaveResource(e);
                i.call("update", {
                    success: function(e)
                    {
                        var i;
                        t.hideLoading(),
                        e.resource_response.error ? e.resource_response.message && (i = {
                            message: e.resource_response.message
                        }) : (P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_CONSUMER_LIST_UPDATED), n.destroy());
                    },
                    error: function(e)
                    {
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("ConsumerManagePage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_CONSUMER_LIST_UPDATED] = this.onListUpdated,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, e);
            },
            showNewDialog: function()
            {
                var e = this;
                P.loadModule({
                        name: "ConsumerNewDialog"
                    },
                    function(t)
                    {
                        e.showInModal(t, {});
                    });
            },
            onListUpdated: function()
            {
                this.render();
            }
        });
    }),
P.Module.define("ConsumerNewDialog", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {
                    name: [P.Validator.Required()],
                    description: [P.Validator.Required()]
                };
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form"), e),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.createConsumer();
            },
            getFormData: function()
            {
                var e = this.$("form").serializeArray(),
                    t = {};
                return _.each(e,
                    function(e)
                    {
                        t[e.name] = e.value;
                    }),
                t;
            },
            getSaveResource: function(e)
            {
                return new P.Resource("ConsumerResource", e);
            },
            createConsumer: function()
            {
                var e = this.getFormData(),
                    t = this.getChildById("submitButton"),
                    n = this;
                t.showLoading();
                var i = this.getSaveResource(e);
                i.call("create", {
                    success: function(e)
                    {
                        var i;
                        t.hideLoading(),
                        e.resource_response.error ? e.resource_response.message && (i = {
                            message: e.resource_response.message
                        }) : (P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_CONSUMER_LIST_UPDATED), n.destroy());
                    },
                    error: function(e)
                    {
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("DatePicker", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.minDate = new Date(2012, 10, 1),
                this.maxDate = this.getYesterday(),
                this.setupPicker(),
                this.setupQuickSelect();
            },
            setupQuickSelect: function()
            {
                var e = {
                    yesterday: this.onYesterdayClick,
                    lastWeek: this.onWeekClick,
                    lastTwoWeeks: this.onTwoWeekClick,
                    lastMonth: this.onMonthClick
                },
                    t = this;
                _.each(e,
                    function(e, n)
                    {
                        var i = t.getChildById(n);
                        i && t.listen(i, P.CONST.EVENT_BUTTON_CLICK, e);
                    });
            },
            updateUsingQuickSelect: function(e)
            {
                "single" === this.options.selectionMode && 2 === e.length && (e = e[0]);
                var t = this.$(".pickerContainer");
                t.DatePickerSetDate(e, !0);
                var n = t.DatePickerGetDate(!0),
                    i = t.DatePickerGetDate(!1);
                this.onChange(n, i);
            },
            onYesterdayClick: function()
            {
                this.updateUsingQuickSelect(this.getYesterday());
            },
            onWeekClick: function()
            {
                var e = this.getYesterday(),
                    t = this.getDaysAgo(7),
                    n = [t, e];
                this.updateUsingQuickSelect(n);
            },
            onTwoWeekClick: function()
            {
                var e = this.getYesterday(),
                    t = this.getDaysAgo(14),
                    n = [t, e];
                this.updateUsingQuickSelect(n);
            },
            onMonthClick: function()
            {
                var e = this.getYesterday(),
                    t = this.getDaysAgo(28),
                    n = [t, e];
                this.updateUsingQuickSelect(n);
            },
            getDaysAgo: function(e)
            {
                var t = new Date;
                return t.setDate(t.getDate() - e),
                t;
            },
            getYesterday: function()
            {
                return this.getDaysAgo(1);
            },
            setupPicker: function()
            {
                var e = this;
                this.$(".pickerContainer").DatePicker({
                    flat: !0,
                    date: this.options.selectedDate || this.getYesterday(),
                    calendars: 1,
                    mode: this.options.selectionMode || "range",
                    starts: 1,
                    onChange: function(t, n)
                    {
                        return e.onChange(t, n);
                    },
                    onRender: function(t)
                    {
                        return e.onDateRender(t);
                    }
                });
            },
            onDateRender: function(e)
            {
                return {
                    disabled: e.valueOf() > this.maxDate.valueOf() || e.valueOf() < this.minDate.valueOf()
                };
            },
            onChange: function(e, t)
            {
                var n = {
                    formatted: e,
                    dates: t
                };
                this.triggerEvent("datePickerDateSelected", n, !0),
                e.length > 1 && e[0] !== e[1] && this.triggerEvent("datePickerRangeSelected", n, !0);
            },
            hidePicker: function()
            {
                this.parent.hide();
            }
        });
    }),
P.Module.define("Developer", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("Domain", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("DomainAnalyticsPage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.childListen(P.CONST.EVENT_DATEPICKER_DATE_SELECTED, this.onDateChanged),
                this.checkValidData();
            },
            checkValidData: function()
            {
                var e = !1;
                $.each(this.data,
                    function(t, n)
                    {
                        (n.PIN_REPIN || n.PIN_VIEW) && (e = !0);
                    }),
                e || (this.$(".noData").show(), this.$(".metricsContainer").hide());
            },
            onDateChanged: function(e)
            {
                var t = e.data.formatted[0],
                    n = e.data.formatted[1];
                if (t !== n)
                {
                    this.showLoading(!0),
                    e.target.parent.hide();
                    var i = window.location.pathname,
                        o = $.param({
                            start_date: t,
                            end_date: n
                        }),
                        s = i + "?" + o;
                    this.navigate(s);
                }
            }
        });
    }),
P.Module.define("DomainFeedPage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.checkGridContent(),
                this.childListen(P.CONST.EVENT_DATEPICKER_DATE_SELECTED, this.onDateChanged);
            },
            checkGridContent: function()
            {
                var e = this.getChildById("feedGrid");
                e.hasItems() || this.$(".noData").show();
            },
            changeDate: function(e)
            {
                var t = (e.endDate - e.startDate) / 6e8,
                    n = {
                        end_date: e.formattedEndDate
                    };
                t >= 2 ? n.aggregation = "biweekly" : t >= 1 && (n.aggregation = "weekly");
                var i = window.location.pathname,
                    o = $.param(n),
                    s = i + "?" + o;
                this.navigate(s);
            },
            onDateChanged: function(e)
            {
                this.showLoading(!0),
                e.target.hidePicker();
                var t = e.data.dates[0],
                    n = e.data.dates[1],
                    i = e.data.formatted[1];
                this.changeDate({
                    startDate: t,
                    endDate: n,
                    formattedEndDate: i
                });
            }
        });
    }),
P.Module.define("DomainInfoBar", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("DomainOwnerInfoBar", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .export": "exportClicked"
            },
            exportMetricsUrl: function()
            {
                return this._buildUrl("", {
                    end_date: this.options.end_date,
                    start_date: this.options.start_date
                });
            },
            exportMostRepinnedUrl: function()
            {
                return this._buildUrl("top/repins/", {
                    end_date: this.options.end_date
                });
            },
            exportMostClickedUrl: function()
            {
                return this._buildUrl("top/clicks/", {
                    end_date: this.options.end_date
                });
            },
            exportMostRecentUrl: function()
            {
                return this._buildUrl("recent/", {});
            },
            _buildUrl: function(e, t)
            {
                this.options.aggregation && (t.aggregation = this.options.aggregation);
                var n = $.param(t),
                    i = "/analytics/" + this.options.domain + "/export/",
                    o = i + e,
                    s = o + "?" + n;
                return s;
            },
            exportClicked: function()
            {
                var e = this.urlExportMap[this.options.feed_item_type];
                e || (e = this.exportMetricsUrl),
                this.downloadFile(e.apply(this));
            },
            downloadFile: function(e)
            {
                var t = "downloaderIFrame",
                    n = document.getElementById(t);
                null === n && (n = document.createElement("iframe"), n.id = t, n.style.display = "none", document.body.appendChild(n)),
                n.src = e;
            },
            initialize: function()
            {
                this.urlExportMap = {
                    most_recent: this.exportMostRecentUrl,
                    most_repinned: this.exportMostRepinnedUrl,
                    most_clicked: this.exportMostClickedUrl
                };
            }
        });
    }),
P.Module.define("DomainVerify", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .helpText a": "onClickType"
            },
            initialize: function()
            {
                this.METATAG = "metatag",
                this.FILENAME = "filename",
                this.verificationType = this.FILENAME;
            },
            onContentReady: function()
            {
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form")),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.downloadButton = this.getChildById("downloadButton"),
                this.listen(this.downloadButton, P.CONST.EVENT_BUTTON_CLICK, this.onClickDownload);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.verifyDomain();
            },
            swapVerificationType: function()
            {
                this.$(".filename, .metaTag").toggle(),
                this.verificationType = this.verificationType === this.METATAG ? this.FILENAME : this.METATAG;
            },
            onClickType: function()
            {
                this.swapVerificationType();
            },
            showError: function(e)
            {
                this.$(".errorReason").text(e),
                this.$(".errorSection").show();
            },
            hideError: function()
            {
                this.$(".errorSection").hide();
            },
            waitForVerification: function(e, t)
            {
                t = t || 3;
                var n = 0,
                    i = new P.Resource("TaskStatusResource", {
                        task_id: e
                    }),
                    o = this,
                    s = function()
                    {
                        n >= t || i.call("get", {
                            success: function(e)
                            {
                                var t = e.resource_response;
                                t.error || ("running" === t.data.status ? setTimeout(s, 200) : "failure" === t.data.data.status ? o.showError(t.data.data.message) : o.isInModal() ? (P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_USER_UPDATED), P.pubsub.publish(P.currentUser.attributes.id, P.CONST.PUBSUB_TOPIC_USER_UPDATED), o.destroy()) : this.navigate("/"));
                            },
                            error: function()
                            {
                                P.showError("Trouble verifying your domain. Please try again later.");
                            }
                        });
                    };
                setTimeout(s, 200);
            },
            verifyDomain: function()
            {
                var e = this.getChildById("submitButton");
                e.showLoading(),
                this.hideError();
                var t = this,
                    n = {
                        type: this.verificationType,
                        domain: this.options.domain
                    },
                    i = new P.Resource("DomainVerifyResource", n);
                i.call("update", {
                    success: function(n)
                    {
                        var i;
                        e.hideLoading(),
                        n.resource_response.error ? n.resource_response.message && (i = {
                            message: n.resource_response.message
                        }) : t.waitForVerification(n.resource_response.data.task_id);
                    },
                    error: function(e)
                    {
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        e.hideLoading();
                    }
                });
            },
            downloadFile: function(e)
            {
                var t = "downloaderIFrame",
                    n = document.getElementById(t);
                null === n && (n = document.createElement("iframe"), n.id = t, n.style.display = "none", document.body.appendChild(n)),
                n.src = e;
            },
            onClickDownload: function()
            {
                this.downloadFile("/website/verify/download/");
            }
        });
    }),
P.Module.define("Dropdown", ["PositionModule"],
    function(e)
    {
        var t = "active",
            n = "dropdownContainer",
            i = "dropdownModule";
        return e.extend({
            initialize: function()
            {
                this.alreadyInitialized = !1,
                this.childListen("cancelClicked", this.disableAnchorAndHideDropdown),
                this.childListen(P.CONST.EVENT_DROPDOWN_HIDE, this.disableAnchorAndHideDropdown),
                this.childListen(P.CONST.EVENT_NAVIGATE, this.disableAnchorAndHideDropdown),
                this.childListen(P.CONST.EVENT_EXTERNAL_CLICK, this.disableAnchorAndHideDropdown),
                e.prototype.initialize.apply(this);
            },
            _positionIfReady: function()
            {
                this.inDom && this.contentReady && (this.positionModule(), this.ensureHoverIntent(), this.getPositionAnchor().initHovering());
            },
            onAdded: function()
            {
                this.options.prefetch && (this.options.prefetch = !1, this.render());
            },
            onAddedToDom: function()
            {
                this._positionIfReady();
            },
            onContentReady: function()
            {
                this._positionIfReady();
            },
            disableAnchorAndHideDropdown: function()
            {
                this.setAnchorActive(!1),
                this.hide();
            },
            render: function(e)
            {
                this.renderContainer(),
                $("body").append(this.$el);
                var t = _.bind(function()
                {
                    this.contentReady = !0,
                    this.onContentReady(),
                    this.onRendered(),
                    e && e();
                },
                    this),
                    n = this.getPositionElement();
                this.options.title && n.append('<h2 class="dropdownTitle">' + this.options.title + "</h2>"),
                this.options.text && n.append('<p class="dropdownText">' + this.options.text + "</p>"),
                this.options.module ? P.loadModule(this.options.module, _.bind(function(e)
                {
                    e.id = i,
                    this.insertChild(e, this.getPositionElement()),
                    e.render(t),
                    this.options.displayWhileLoading && t();
                },
                    this)) : t();
            },
            setAnchorActive: function(e)
            {
                this.parent.setActiveStyle(e);
            },
            ensureHoverIntent: function()
            {
                var e = this;
                this.parent.isClickButton() || this._hoverIntent || this.options.manually_close || (this._hoverIntent = new P.HoverIntent(this.$el, {
                        exitDelay: 500
                    }), this.listen(this._hoverIntent, P.CONST.EVENT_HOVERINTENT_OUT_COMPLETE,
                        function()
                        {
                            e.getPositionAnchor().isHovering() || (e.hide(), e.setAnchorActive(!1));
                        }));
            },
            hide: function()
            {
                this.$el.removeClass(t),
                this.triggerEvent(P.CONST.EVENT_DROPDOWN_HIDE, null, !0),
                this._bodyListener && (this.removeListener(this._bodyListener), this._bodyListener = null),
                this._dropdownSubscriber && (this._dropdownSubscriber.unsubscribe(), this._dropdownSubscriber = null);
            },
            ensureModule: function(e)
            {
                var t = this;
                return e = e || P.NOOP,
                this.rendering || this.getChildById(i) ? e() : (this.rendering = !0, this.render(function()
                {
                    return t.rendering = !1,
                    e();
                }), void 0);
            },
            ensureOpenListeners: function()
            {
                this.options.sticky || (this._bodyListener = this.listen($("body"), "mousedown",
                    function(e)
                    {
                        $(e.target).closest(this.$el).length > 0 || $(e.target).closest(this.options.anchor).length > 0 || this.hide();
                    }));
            },
            show: function(e)
            {
                var n = this;
                this.ensureOpenListeners(),
                this.ensureModule(function()
                {
                    n.$el.addClass(t),
                    n.positionModule(),
                    n.triggerEvent(P.CONST.EVENT_DROPDOWN_SHOW, null, !0),
                    e && e();
                });
            },
            fadeIn: function(e, t)
            {
                var n = this;
                this.show(function()
                {
                    n.$el.addClass("fadeIn"),
                    t && t();
                });
            },
            getDropdown: function()
            {
                return this.$("." + n);
            },
            isVisible: function()
            {
                return this.$el.hasClass(t);
            }
        });
    }),
P.Module.define("DropdownButton", ["Dropdown"],
    function(e)
    {
        var t = "tutorialDropdown",
            n = "click",
            i = "hover",
            o = {};
        return o[n] = n,
        o[i] = i,
        P.Module.extend({
            events: {
                click: "onClick"
            },
            handleClick: function(e)
            {
                if (this.openStrategy === i)
                {
                    return !1;
                }
                var t = this._dropdown.isVisible();
                t ? this.hideDropdown() : (this.showDropdown(), e.stopPropagation());
            },
            onClick: function(e)
            {
                this.handleClick(e);
            },
            getDropdown: function()
            {
                return this.getChildById("dropdown");
            },
            getDropdownOptions: function()
            {
                return this.options.dropdown_options || {};
            },
            getDropdownModule: function()
            {
                return this.options.module;
            },
            ensureDropdown: function()
            {
                if (this.getDropdown())
                {
                    return this._dropdown;
                }
                var t = {
                    module: this.getDropdownModule(),
                    anchor: this.getElement()
                };
                _.map(this.getDropdownOptions(),
                    function(e, n)
                    {
                        t[n] = e;
                    });
                var n = this._dropdown = new e({
                    options: t,
                    id: "dropdown"
                });
                this.listen(n, P.CONST.EVENT_DROPDOWN_HIDE, this.onDropdownHide),
                this.addChild(n);
            },
            onMouseEnterComplete: function()
            {
                this.isHoverEnabled() && this.$el.isHovering() && this.showDropdown();
            },
            showDropdown: function(e)
            {
                this.setActiveStyle(!0),
                this.hideTutorial(),
                this._dropdown.show(e);
            },
            hideDropdown: function()
            {
                this.setActiveStyle(!1),
                this._dropdown.hide();
            },
            onMouseOutComplete: function()
            {
                this._dropdown.$el.isHovering() || this.hideDropdown();
            },
            initListeners: function()
            {
                var e = this;
                this.openStrategy !== n && (this._hoverIntent && this._hoverIntent.$el === this.$el || (this._hoverIntent = new P.HoverIntent(this.$el, {
                        enterDelay: 5,
                        exitDelay: 200
                    }), this.listen(this._hoverIntent, P.CONST.EVENT_HOVERINTENT_ENTER_COMPLETE,
                        function()
                        {
                            e.onMouseEnterComplete();
                        }), this.listen(this._hoverIntent, P.CONST.EVENT_HOVERINTENT_OUT_COMPLETE,
                            function()
                            {
                                e.onMouseOutComplete();
                            })));
            },
            onContentReady: function()
            {
                this.ensureDropdown(),
                this.$el.initHovering(),
                this._dropdown.$el.initHovering(),
                this.openStrategy = this.options.show_dropdown_on_hover ? o[i] : o[n],
                this.initListeners(),
                this.options.tutorial && this.options.tutorial.topic && (this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_TUTORIAL, _.object([[this.options.tutorial.topic, this.onShowTutorial]])), this.options.tutorial.show && this.showTutorial());
            },
            onDropdownHide: function()
            {
                this.setActiveStyle(!1);
            },
            ensureTutorialDropdown: function()
            {
                if (!this.getChildById(t))
                {
                    var n = _.extend({},
                        this.options.dropdown_options, {
                            title: this.options.tutorial.title,
                            text: this.options.tutorial.text,
                            anchor: this.getElement(),
                            class_name: "tutorial",
                            largeCaret: !1
                        }),
                        i = new e({
                            id: t,
                            options: n
                        });
                    this.appendChild(i);
                }
                return this.getChildById(t);
            },
            onShowTutorial: function()
            {
                this.showTutorial();
            },
            isClickButton: function()
            {
                return this.openStrategy === n;
            },
            showTutorial: function()
            {
                if (this.options.tutorial)
                {
                    var e = this.ensureTutorialDropdown();
                    e.fadeIn(1e3);
                }
            },
            hideTutorial: function()
            {
                if (this.options.tutorial)
                {
                    var e = this.getChildById(t);
                    e && e.destroy();
                }
            },
            setActiveStyle: function(e)
            {
                var t = this.getChildByModuleName("Button");
                t ? t.$el.toggleClass(P.CONST.CLASS_DROPDOWN_BUTTON_ACTIVE, e) : this.$el.toggleClass(P.CONST.CLASS_DROPDOWN_BUTTON_ACTIVE, e);
            },
            isHoverEnabled: function()
            {
                return (!this.options.button_options || this.options.button_options.disabled !== !0) && this.openStrategy !== n;
            }
        });
    }),
P.Module.define("FacebookShareButton", ["Button"],
    function(e)
    {
        return e.extend({
            onClick: function()
            {
                var e = this.options.ga_category || "share_facebook";
                return P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK),
                P.FacebookDialog.open(this.options.dialog_options),
                !1;
            }
        });
    }),
P.Module.define("FastFollow", ["Grid"],
    function(e)
    {
        var t = "fastFollowContent",
            n = "fastFollowHeader",
            i = "categoryBoardsGrid",
            o = 355,
            s = 102,
            r = 56,
            a = P.Module.extend({
                _boardsFollowed: [],
                _modalDisplayed: !1,
                _cachedGrids: {},
                getOwnedScrollables: function()
                {
                    return this.$(".fastFollowGridContainer");
                },
                _getBoardIdFromEvent: function(e)
                {
                    var t = e.data || {};
                    return t.board_id;
                },
                _onBoardFollow: function(e)
                {
                    var t = this._getBoardIdFromEvent(e),
                        n = $.inArray(t, this._boardsFollowed);
                    t && -1 === n && (this._boardsFollowed.push(t), this._updateFollowedBoards(1));
                },
                _onBoardUnfollow: function(e)
                {
                    var t = this._getBoardIdFromEvent(e);
                    if (t)
                    {
                        var n = $.inArray(t, this._boardsFollowed);
                        -1 !== n && (this._boardsFollowed.splice(n, 1), this._updateFollowedBoards(-1));
                    }
                },
                _onCategoryUpdate: function(n)
                {
                    var o = n.data;
                    if (this._currentGrid || (this._currentGrid = this.getChildById(i), this._cachedGrids[this._currentGrid.resource.options.category] = this._currentGrid), o !== this._currentGrid.resource.options.category)
                    {
                        this._currentGrid.remove();
                        var s = this._cachedGrids[o];
                        s || (s = new e({
                            id: i,
                            options: {
                                centered: !1,
                                layout: "fixed_height",
                                show_grid_footer: !1,
                                scrollable: !0,
                                item_options: {
                                    allow_click_thru: !1
                                }
                            },
                            resource: {
                                name: "CategoryBoardsResource",
                                options: {
                                    category: o
                                }
                            }
                        }), s.render(), this._cachedGrids[o] = s);
                        var r = this.$(".fastFollowGridContainer");
                        this.$("." + t).scrollTop(0),
                        this.insertChild(s, r),
                        this._currentGrid = s;
                    }
                },
                _onProgressCompletion: function()
                {
                    this._userRegisterTrackActionOrientationComplete(),
                    this._setProgressCompletion(!0),
                    P.currentUser.set("show_fast_follow", !1);
                },
                _userRegisterTrackActionOrientationComplete: function()
                {
                    P.trackRegisterAction("orientation_complete");
                },
                _setProgressCompletion: function(e)
                {
                    var t = this.getChildById(n);
                    t && (t.options.progress_completed = e, t.render());
                },
                _updateFollowedBoards: function(e)
                {
                    if (!this._modalDisplayed)
                    {
                        var t = this.getChildById(n);
                        t && t.stepProgress(e);
                    }
                },
                onContentReady: function()
                {
                    var e = this;
                    _.each(this.extraData.followed_boards,
                        function(t)
                        {
                            e._boardsFollowed.push(t.id);
                        }),
                    this.childListen(P.CONST.EVENT_FAST_FOLLOW_CATEGORY_SELECTED, this._onCategoryUpdate),
                    this.childListen(P.CONST.EVENT_PROGRESS_COMPLETED, this._onProgressCompletion),
                    this.childListen(P.CONST.EVENT_BOARD_FOLLOW, this._onBoardFollow, this),
                    this.childListen(P.CONST.EVENT_BOARD_UNFOLLOW, this._onBoardUnfollow, this),
                    this.listen(P.Viewport, P.CONST.EVENT_RESIZE, this.position),
                    this.position();
                },
                position: function()
                {
                    if (this.inDom && this.contentReady)
                    {
                        this.fastFollowHeaderHeight || (this.fastFollowHeaderHeight = this.$(".FastFollowHeader").outerHeight(!0));
                        var e = s + r,
                            t = P.Viewport.height,
                            n = t - e - this.fastFollowHeaderHeight,
                            i = Math.max(o, n);
                        this.$(".fastFollowContent").height(i);
                    }
                },
                onDestroyed: function()
                {
                    _.each(_.values(this._cachedGrids),
                        function(e)
                        {
                            e.destroy();
                        });
                }
            });
        return a;
    }),
P.Module.define("FastFollowHeader", [],
    function()
    {
        var e = "followPageProgress";
        return P.Module.extend({
            events: {},
            stepProgress: function(t)
            {
                var n = this.getChildById(e);
                n && n.moveStep(t);
            }
        });
    }),
P.Module.define("FastFollowSidebar", [],
    function()
    {
        var e = "selected",
            t = P.Module.extend({
                events: {
                    "click .followPageSidebarCategory": "onCategoryClick"
                },
                onContentReady: function()
                {
                    this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.toggleShowMoreCategories);
                },
                onCategoryClick: function(e)
                {
                    var t = $(e.currentTarget);
                    if (t.length)
                    {
                        var n = t.attr("data-category");
                        n.length && (this.highlightCategory(n), this.triggerEvent(P.CONST.EVENT_FAST_FOLLOW_CATEGORY_SELECTED, n, !0));
                    }
                },
                highlightCategory: function(t)
                {
                    this.$("." + e).removeClass(e),
                    this.$("*[data-category=" + t + "]").addClass(e);
                },
                toggleShowMoreCategories: function()
                {
                    return this.$el.toggleClass("expand"),
                    !1;
                }
            });
        return t;
    }),
P.Module.define("FeedPage", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_CURRENT_CATEGORY, this.options.feed);
            },
            onRemovedFromDom: function()
            {
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_CURRENT_CATEGORY, null);
            }
        });
    }),
P.Module.define("FindFriendsContent", ["SocialNetworkSettingsBase"],
    function(e)
    {
        var t = 1e3,
            n = 110;
        return e.extend({
            events: {},
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onButtonClick: function(e)
            {
                var t = e.target,
                    n = null;
                switch (t.id)
                {
                    case "facebookConnectButton":
                        n = P.SocialConnect.FACEBOOK;
                        break;
                    case "twitterConnectButton":
                        n = P.SocialConnect.TWITTER;
                        break;
                    default:
                        return;
                }
                t.showLoading(!0);
                var i = this,
                    o = {
                        success: function()
                        {
                            i.pollForFriends(n);
                        },
                        error: function()
                        {
                            i.hideLoading();
                        }
                    };
                this.handleConnect(n, !0, o);
            },
            _getResourceNameForNetworkFriends: function(e)
            {
                var t = null;
                switch (e)
                {
                    case P.SocialConnect.FACEBOOK:
                        t = "UserFacebookFriendsResource";
                        break;
                    case P.SocialConnect.TWITTER:
                        t = "UserTwitterFriendsResource";
                        break;
                    default:
                        return;
                }
                return t;
            },
            pollForFriends: function(e)
            {
                var i = this._getResourceNameForNetworkFriends(e);
                if (i)
                {
                    var o = new P.Resource(i, {
                        username: this.options.username
                    }),
                        s = this;
                    o.call("get", {
                        success: function()
                        {
                            s.render();
                        },
                        error: function(i)
                        {
                            i.api_error_code === n ? setTimeout(function()
                            {
                                s.pollForFriends(e);
                            },
                                t) : (s.hideLoading(), s.render());
                        }
                    });
                }
            }
        });
    }),
P.Module.define("FindFriendsInfoBar", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("FindFriendsPage", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("FindFriendsRep", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("FlagComment", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.$("form"),
                    t = {
                        reason: [P.Validator.Required()]
                    },
                    n = {
                        prevalidate: !0
                    };
                this.form = new P.Form(e, t, n),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.flagComment();
            },
            flagComment: function()
            {
                var e = this,
                    t = this.getChildById("submitButton");
                t.showLoading();
                var n = {
                    pin_id: this.options.pin_id,
                    comment_id: this.options.comment_id,
                    reason: this.$("form :checked").attr("value")
                };
                "other" === n.reason && (n.explanation = this.$("textarea").val()),
                P.trackGAEvent("comment_flag", P.CONST.GA_ACTION_CLICK_SUBMIT, "reason", n.reason);
                var i = new P.Resource("CommentFlagResource", n);
                i.call("create", {
                    success: function()
                    {
                        P.trackGAEvent("comment_flag", P.CONST.GA_ACTION_SUCCESS),
                        e.destroy();
                    },
                    error: function(e)
                    {
                        P.trackGAEvent("comment_flag", P.CONST.GA_ACTION_ERROR),
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("FlagCommentReasons", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("FlagContent", [],
    function()
    {
        var e = "hidden",
            t = "active",
            n = "other";
        return P.Module.extend({
            events: {
                "change input": "onChange"
            },
            initialize: function()
            {
                this.listen(this, "change", this.checkIfOtherIsSelected);
            },
            onChange: function(e)
            {
                var t = this,
                    n = this.options,
                    i = $(e.target),
                    o = i.siblings("label");
                if (this._reason = i.attr("id"), this._reasonNoun = o.text(), this.checkIfOtherIsSelected(), this.triggerEvent("change", this, !0), "blockInput" === n.class_name && this.updateLabel(i), n.reason = this._reason, n.reason_noun = this._reasonNoun, this.options.show_confirmation_on_change)
                {
                    var s = {
                        name: "FlagContentConfirm",
                        options: n
                    };
                    P.loadModule(s,
                        function(e)
                        {
                            var i;
                            "user" === n.object_flagged ? i = "user_flag" : "pin" === n.object_flagged ? i = "pin_flag" : "comment" === n.object_flagged && (i = "comment_flag"),
                            i && P.trackGAEvent(i, P.CONST.GA_ACTION_OPEN_MODAL, "reason", t._reason),
                            t.hideLoading(),
                            t.showInModal(e);
                        });
                }
            },
            updateLabel: function(e)
            {
                var n = $(e),
                    i = n.siblings("label");
                this.$("." + t).removeClass(t),
                i.addClass(t);
            },
            showOtherFieldIfNeed: function()
            {
                this.options.hide_other_field || this.$(".explanation").toggleClass(e, !this.options.show_explanation);
            },
            checkIfOtherIsSelected: function()
            {
                this.options.show_explanation = this._reason === n ? !0 : !1,
                this.showOtherFieldIfNeed();
            }
        });
    }),
P.Module.define("FlagContentConfirm", [],
    function()
    {
        var e = "user_flag";
        return P.Module.extend({
            onContentReady: function()
            {
                var e = this.$("form"),
                    t = {};
                this.options.show_explanation && (t = {
                    explanation: [P.Validator.Required(), P.Validator.Length({
                        max: P.CONST.MAX_CHARS_FOR_BOARD_TITLE
                    })]
                });
                var n = {
                    prevalidate: !0
                };
                this.form = new P.Form(e, t, n),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onButtonClick: function(t)
            {
                var n = t.target;
                n && ("cancelButton" === n.id ? P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK_CANCEL) : "reportButton" === n.id && P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK_SUBMIT));
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.reportUser();
            },
            onReportUserSuccess: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "flag_user_success"
                        }
                    };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM, e.onFlagConfirm);
                    });
            },
            onFlagConfirm: function()
            {
                this.destroy();
            },
            reportUser: function()
            {
                var t = this,
                    n = this.options.user_id,
                    i = {
                        reported_user: n,
                        reason: this.options.reason
                    };
                this.options.show_explanation && (i.explanation = this.$("textarea").val());
                var o = new P.Resource("UserReportResource", i);
                o.call("create", {
                    success: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_SUCCESS),
                        t.onReportUserSuccess();
                    },
                    error: function(t)
                    {
                        P.showError(t.message),
                        P.trackGAEvent(e, P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        t.destroy();
                    }
                });
            }
        });
    }),
P.Module.define("FlagPin", [],
    function()
    {
        var e = "pin_flag";
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.$("form"),
                    t = {
                        reason: [P.Validator.Required()]
                    },
                    n = {
                        prevalidate: !0
                    };
                this.form = new P.Form(e, t, n),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.flagPin();
            },
            flagPin: function()
            {
                var t = this,
                    n = this.getChildById("submitButton");
                n.showLoading();
                var i = {
                    pin_id: this.options.pin_id,
                    reason: this.$("form :checked").attr("value")
                };
                "other" === i.reason && (i.explanation = this.$("textarea").val());
                var o = {
                    name: "ConfirmDialog",
                    options: {
                        template: "flag_pin"
                    }
                };
                P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK_SUBMIT, "reason", i.reason);
                var s = new P.Resource("PinFlagResource", i);
                s.call("create", {
                    success: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_SUCCESS),
                        P.loadModule(o,
                            function(e)
                            {
                                t.showInModal(e),
                                t.listen(e, P.CONST.EVENT_CONFIRM, t.destroy);
                            });
                    },
                    error: function(t)
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_ERROR),
                        P.showError(t.message);
                    },
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("FlagUser", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .cancelButton": "onCancelButtonClick"
            },
            onCancelButtonClick: function()
            {
                var e = this.options.blocked_by_me ? "user_unblock" : "user_block";
                P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK_CANCEL),
                this.triggerEvent("cancelClicked", this, !0);
            }
        });
    }),
P.Module.define("FlagUserPinReasons", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("FriendsToFollow", [],
    function()
    {
        return P.Module.extend({
            events: {},
            friendIdsUsed: [],
            friendIdsUnused: [],
            usersToReplace: [],
            usersDismissing: [],
            onContentReady: function()
            {
                this.friendIdsUsed = this.extraData.friendIdsUsed,
                this.destroyIfEmpty() || (this.childListen(P.CONST.EVENT_DISMISS, this.onChildDismiss), this.childListen(P.CONST.EVENT_USER_FOLLOW, this.onChildUserFollow));
            },
            onChildDismiss: function(e)
            {
                var t = e.target,
                    n = new P.Resource("UserFriendSuggestionResource", {});
                n.set("user_id", t.getUserId()),
                n.call("delete"),
                this.dismissUser(t);
            },
            onChildUserFollow: function(e)
            {
                var t = e.target,
                    n = this;
                window.setTimeout(function()
                {
                    n.dismissUser(t);
                },
                    500);
            },
            requestMoreFriendsIfNeeded: function()
            {
                var e = this.friendIdsUnused,
                    t = this.usersDismissing.length + this.usersToReplace.length;
                if (!(e.length >= t || this.resource.xhr))
                {
                    var n = this;
                    this.resource.resetBookmark(),
                    this.resource.options.excluded_user_ids = this.friendIdsUsed,
                    this.resource.call("get", {
                        success: function(t)
                        {
                            var i = t.resource_response.data,
                                o = _.pluck(i, "id");
                            for (n.friendIdsUnused = e.concat(o); n.usersToReplace.length;)
                            {
                                var s = n.usersToReplace.shift();
                                n.replaceUser(s);
                            }
                        }
                    });
                }
            },
            dismissUser: function(e)
            {
                if (e)
                {
                    var t = this;
                    this.usersDismissing.push(e),
                    e.fadeOut(function()
                    {
                        t.usersDismissing = _.without(t.usersDismissing, e),
                        t.friendIdsUnused.length ? t.replaceUser(e) : (t.usersToReplace.push(e), t.requestMoreFriendsIfNeeded());
                    });
                }
            },
            removeUser: function(e)
            {
                var t = e.$el.parent();
                t.remove(),
                e.destroy();
                var n = this.getChildById("friendList");
                n.isEmpty() && this.destroy();
            },
            replaceUser: function(e)
            {
                var t = this.friendIdsUnused.pop();
                return t ? (e.resource.options.user_id = t, e.render(function()
                {
                    e.show(),
                    e.fadeIn();
                }), this.friendIdsUsed.push(t), void 0) : (this.removeUser(e), void 0);
            }
        });
    }),
P.Module.define("Grid", [],
    function()
    {
        var e = "hasError";
        return P.Module.extend({
            events: {
                "click .gridFooter .gridError .Button": "onTryAgainClick"
            },
            initialize: function(e)
            {
                e.options.show_grid_footer && (this.childListen(P.CONST.EVENT_ERROR, this.onError), this.childListen(P.CONST.EVENT_ERROR_RESOLVED, this.onErrorResolved), this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick), this.childListen(P.CONST.EVENT_ITEMS_REQUEST_START, this.onItemsRequestStart), this.childListen(P.CONST.EVENT_ITEMS_REQUEST_SUCCESS, this.onItemsRequestSuccess), this.childListen(P.CONST.EVENT_ITEMS_END, this.onItemsEnd));
            },
            onContentReady: function()
            {
                this.items = this.getChildByModuleName("GridItems"),
                this.footer = this.getChildByModuleName("GridFooter"),
                this.footer && this.hasItems() && this.footer.show();
            },
            hasItems: function()
            {
                return this.items.hasItems();
            },
            hasItemsOfType: function(e)
            {
                return !!this.items.getChildrenByModuleName(e).length;
            },
            hasMoreItems: function()
            {
                return this.items.hasMoreItems();
            },
            requestMoreItems: function()
            {
                this.items.requestMoreItems();
            },
            emptyItems: function()
            {
                this.items.empty();
            },
            renderItems: function(e, t)
            {
                this.items.render(e, t);
            },
            setPageSize: function(e)
            {
                this.items.setPageSize(e);
            },
            getItemsResource: function()
            {
                return this.items.resource;
            },
            setItemsResource: function(e)
            {
                this.setResource(e),
                this.items && this.items.setResource(e);
            },
            onError: function()
            {
                this.hasError = !0,
                this.$el.addClass(e),
                this.footer && (this.footer.showError(), this.footer.hideGridLoading());
            },
            onErrorResolved: function()
            {
                this.hasError && (this.hasError = !1, this.$el.removeClass(e));
            },
            onButtonClick: function()
            {
                return this.requestMoreItems(),
                !1;
            },
            onItemsRequestStart: function()
            {
                this.footer && this.footer.showGridLoading();
            },
            onItemsRequestSuccess: function()
            {
                this.footer && this.footer.hideError();
            },
            onItemsEnd: function()
            {
                this.footer && this.footer.hideGridLoading();
            },
            prependChildItem: function(e)
            {
                this.getGridItems().prependChildItem(e);
            },
            prependNewItems: function(e, t)
            {
                return this.getGridItems().prependNewItems(e, t);
            },
            getGridItems: function()
            {
                return this.items;
            },
            getFirstGridItem: function(e)
            {
                return this.getGridItems().getChildByModuleName(e);
            }
        });
    }),
P.Module.define("GridFooter", [],
    function()
    {
        var e = "showGridLoading";
        return P.Module.extend({
            events: {
                "click .gridError .Button": "onTryAgainClick"
            },
            onTryAgainClick: function(e)
            {
                this.triggerEvent(P.CONST.EVENT_BUTTON_CLICK, e, !0);
            },
            show: function()
            {
                this.$el.css("display", "block");
            },
            _getErrorDiv: function()
            {
                return this.$el.find(".gridError");
            },
            showError: function()
            {
                var e = this._getErrorDiv();
                e.css("display", "block");
            },
            hideError: function()
            {
                var e = this._getErrorDiv();
                e.css("display", "none");
            },
            showGridLoading: function()
            {
                this.$el.addClass(e);
            },
            hideGridLoading: function()
            {
                this.$el.removeClass(e);
            }
        });
    }),
P.Module.define("GridItems", [],
    function()
    {
        var e = "activeItem",
            t = 3,
            n = 1e3,
            i = 3e3,
            o = 1e3,
            s = "gridSortable",
            r = {
                UP: 0,
                DOWN: 1
            },
            a = function(e)
            {
                var t = parseInt(e.replace("px", ""), 10);
                return isNaN(t) ? 0 : t;
            },
            l = function(e)
            {
                this.childModule = e,
                this.top = null,
                this.height = null,
                this.bottom = null,
                this.$itemWrapper = e.getParentElement().closest(".item"),
                this.columnIndex = null,
                this.inDom = !0;
            };
        l.prototype = {
            _calculateHeight: function()
            {
                this.height = this.$itemWrapper.height();
            },
            ensureHeightCalculated: function()
            {
                null === this.height && this._calculateHeight();
            },
            recalculateHeight: function()
            {
                this.inDom ? this._calculateHeight() : this.log.error("Cannot calculate height because this item is not inDom");
            },
            setPosition: function(e, t)
            {
                this.top = e,
                this.bottom = t;
            },
            hasPosition: function()
            {
                return null !== this.top;
            }
        };
        var u = function(e, t)
        {
            this.gridItems = e,
            this.options = t,
            this.shortestColumnIndex = 0,
            this.columnLengths = [],
            this.childCidToItemInfo = {};
            var n = this;
            _.each(this.gridItems.children,
                function(e)
                {
                    n.childCidToItemInfo[e.cid] = new l(e);
                });
        };
        u.prototype = {
            getFilledHeight: function()
            {
                return this.columnLengths[this.shortestColumnIndex];
            },
            onChildRendered: function(e)
            {
                this._reflowOnChildChanged(e);
            },
            onChildAdded: function(e)
            {
                this.childCidToItemInfo[e.cid] = new l(e);
            },
            onChildRemoved: function(e, t)
            {
                if (!this.gridItems.isEmptying)
                {
                    t.remove();
                    var n = this.childCidToItemInfo[e.cid],
                        i = n.columnIndex;
                    delete this.childCidToItemInfo[e.cid],
                    this._reflowColumnContent(i);
                }
            },
            empty: function()
            {
                this.childCidToItemInfo = {};
            },
            onChildContentChanged: function(e)
            {
                this._reflowOnChildChanged(e);
            },
            onChildDimsChanged: function(e)
            {
                this._reflowOnChildChanged(e, !1);
            },
            _reflowOnChildChanged: function(e, t)
            {
                var n = this.childCidToItemInfo[e.cid];
                n.recalculateHeight(),
                this._reflowColumnContent(n.columnIndex, t);
            },
            _reflowColumnContent: function(e, t)
            {
                void 0 === t && (t = this.options.reflow_all),
                t ? this.positionGrid() : this._repositionItemsInColumn(e);
            },
            _calculateNumColumns: function()
            {
                var e = this.options.minimum_num_columns || t;
                if (!this.itemWidth)
                {
                    return e;
                }
                this.options.centered || this.gridItems.$el.css("width", "auto");
                var n = this.gridItems.getWidth(!1),
                    i = Math.floor(n / this.itemWidth);
                return Math.max(e, i);
            },//列显示 排列
            _positionItemInColumn: function(e, t)
            {
                if (this.gridItems.isReady())
                {
                    var n = this.childCidToItemInfo[e.cid],
                        i = n.$itemWrapper;
                    t = Math.max(0, t),
                    t = Math.min(this.columnLengths.length - 1, t);
                    var o = this.columnLengths[t];
                    i.css({
                        top: o + "px",
                        left: t * this.itemWidth + "px",
                        visibility: "visible"
                    }),
                    n.columnIndex = t;
                    var s = n.height + this.topBuffer + this.bottomBuffer,
                        r = o + s;
                    n.setPosition(o, r),
                    this.columnLengths[t] = r,
                    this._setShortestColumnIndex();
                }
            },//获取位置
            _positionItem: function(e)
            {
                if (this.gridItems.isReady())
                {
                    if (0 === this.columnLengths.length)
                    {
                        if (!this.itemWidth)
                        {
                            var t = this.childCidToItemInfo[e.cid],
                                n = t.$itemWrapper;
                            this.itemWidth = n.outerWidth(!0);
                            var i = n.css("margin-top"),
                                o = n.css("padding-top"),
                                s = n.css("margin-bottom"),
                                r = n.css("padding-bottom");
                            this.topBuffer = a(i) + a(o),
                            this.bottomBuffer = a(s) + a(r);
                        }
                        var l = this._calculateNumColumns();
                        this.options.centered || this.gridItems.$el.css("width", l * this.itemWidth),
                        this.columnLengths = Array(l),
                        this._setShortestColumnIndex();
                    }
                    var u = this.shortestColumnIndex;
                    this._positionItemInColumn(e, u);
                }
            },
            _setShortestColumnIndex: function()
            {
                this.shortestColumnIndex = 0;
                for (var e = 0; e < this.columnLengths.length; e++)
                {
                    this.columnLengths[e] = this.columnLengths[e] || 0,
                    this.columnLengths[e] < this.columnLengths[this.shortestColumnIndex] && (this.shortestColumnIndex = e);
                }
            },
            _repositionItemsInColumn: function(e)
            {
                if (this.gridItems.isReady())
                {
                    var t = this;
                    this.columnLengths[e] = 0;
                    var n = _.filter(this.childCidToItemInfo,
                        function(t)
                        {
                            return t.columnIndex === e;
                        }),
                        i = _.sortBy(n,
                            function(e)
                            {
                                return e.top;
                            });
                    _.each(i,
                        function(n)
                        {
                            t._positionItemInColumn(n.childModule, e);
                        }),
                    this.resizeContainer();
                }
            },
            resizeGrid: function()
            {
                var e = this.columnLengths.length,
                    t = this._calculateNumColumns();
                e !== t && (this.positionGridChildren(), this.gridItems.rearrangeItems(!0));
            },
            resizeContainer: function()
            {
                var e = Math.max.apply(Math, this.columnLengths);
                this.gridItems.$el.css("height", e + "px"),
                this.gridItems.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
            },
            positionGrid: function()
            {
                this.gridItems.isReady() && (this.positionGridChildren(), this.gridItems.rearrangeItems());
            },//设置项的位置
            positionGridChildren: function(e)
            {
                if (this.gridItems.isReady())
                {
                    var t = this;
                    e || (this.columnLengths = []),
                    _.each(this.gridItems.children,
                        function(e)
                        {
                            var n = t.childCidToItemInfo[e.cid];
                            n.ensureHeightCalculated();
                        }),
                    _.each(this.gridItems.children,
                        function(n)
                        {
                            var i = t.childCidToItemInfo[n.cid];
                            e && i.hasPosition() || t._positionItem(i.childModule);
                        }),
                    this.resizeContainer();
                }
            },
            hideAndShowItems: function(e, t, n, i, o)
            {
                var s = this,
                    a = [],
                    l = [];
                _.each(this.childCidToItemInfo,
                    function(s)
                    {
                        var u = s.$itemWrapper[0];
                        s.bottom < i ? e && s.inDom && (t || n !== r.DOWN || (a.push(u), s.inDom = !1)) : s.top > o ? e && s.inDom && (t || n !== r.UP || (a.push(u), s.inDom = !1)) : s.inDom || (l.push(u), s.inDom = !0);
                    }),
                (l.length > 0 || a.length > 0) && P.deferDomManipulation(function()
                {
                    s.gridItems.log.debug("hideAndShowItems DOM manip showing ", l.length, " hiding ", a.length);
                    var e;
                    if (l.length > 0)
                    {
                        var t = document.createDocumentFragment();
                        for (e = 0; e < l.length; e++)
                        {
                            t.appendChild(l[e]);
                        }
                        s.gridItems.$el[0].appendChild(t);
                    }
                    for (e = 0; e < a.length; e++)
                    {
                        var n = a[e];
                        n.parentNode && n.parentNode.removeChild(n);
                    }
                });
            }
        };
        var c = function(e, t)
        {
            this.gridItems = e,
            this.options = t;
        };
        c.prototype = {
            resizeGrid: function()
            {
            },
            onChildContentChanged: function()
            {
            },
            onChildDimsChanged: function()
            {
            },
            onChildRendered: function()
            {
            },
            onChildAdded: function()
            {
            },
            positionGridChildren: function()
            {
            },
            empty: function()
            {
            },
            positionGrid: function()
            {
                this.gridItems.isReady() && this.gridItems._requestMoreItemsIfNeeded();
            },
            hideAndShowItems: function()
            {
            },
            onChildRemoved: function(e, t)
            {
                t.remove(),
                this.gridItems.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
            },
            getFilledHeight: function()
            {
                var e = this.gridItems.getWidth(!1),
                    t = this.gridItems.children.length;
                if (0 === t)
                {
                    return 0;
                }
                var n = this.gridItems.children[0],
                    i = n.$el.outerWidth(!0),
                    o = n.$el.outerHeight(!0),
                    s = Math.floor(e / i),
                    r = Math.ceil(t / s),
                    a = 0 !== t % s,
                    l = r * o;
                return a && (l -= o),
                l;
            }
        };
        var d = function(e, t, n, i)
        {
            this.gridItems = e,
            t || (t = {}),
            t = _.extend({
                    containment: "parent",
                    cursor: "move",
                    items: "." + s,
                    zIndex: o
                },
                t),
            this.gridItems.$el.sortable(t),
            this.childModuleName = n,
            this.idFn = i,
            this._setSortableMetadata();
        };
        d.prototype = {
            _setSortableMetadata: function()
            {
                var e = this;
                _.each(this.gridItems.getChildrenByModuleName(this.childModuleName),
                    function(t)
                    {
                        e._setSortableMetadataOnModule(t);
                    });
            },
            _setSortableMetadataOnModule: function(e)
            {
                e.$el.attr("data-sort-id", this.idFn(e));
                var t = e.getParentElement();
                t.addClass(s);
            },
            onChildAdded: function(e)
            {
                this._setSortableMetadataOnModule(e);
            },
            getSortOrder: function()
            {
                var e = [];
                return _.each(this.gridItems.$el.find("." + this.childModuleName),
                    function(t)
                    {
                        e.push($(t).attr("data-sort-id"));
                    }),
                e;
            }
        };
        var h = P.Module.extend({
            events: {
                "click .trackActiveItem .item": "onTrackItemClick"
            },
            mixins: [P.Mixins.PreventScroll],
            onChildNavigate: function(e)
            {
                var t = e.currentTarget;
                this.updateActiveItem(t.getParentElement());
            },
            onTrackItemClick: function(e)
            {
                var t = e.currentTarget;
                this.updateActiveItem($(t));
            },
            updateActiveItem: function(t)
            {
                var n = this.$(".activeItem");
                n.removeClass(e),
                t.addClass(e);
            },
            initialize: function()
            {
                this._scrollListener = null,
                this.alreadyInitialized = !1,
                this.scrollTop = 0,
                this.lastScrollTop = null,
                this.viewableHeight = null,
                this.lastTopBorder = null,
                this.lastBottomBorder = null,
                this.layoutManager = null,
                this.childListen(P.CONST.EVENT_CONTENT_CHANGED, this.onChildContentChanged),
                this.childListen(P.CONST.EVENT_DIMS_CHANGED, this.onChildDimsChanged);
            },
            initializeSortManager: function(e, t, n)
            {
                this.sortManager = new d(this, e, t, n);
            },
            getSortOrder: function(e, t)
            {
                return this.sortManager ? this.sortManager.getSortOrder(e, t) : void 0;
            },
            onOptionsChanged: function()
            {
                this._setScrollableElement(),
                this.alreadyInitialized = !1;
            },
            onResourceChanged: function()
            {
                this.alreadyInitialized = !1;
            },
            prependChildItem: function(e)
            {
                var t = 0;
                this.children.length > 0 && this.children[0].options.anchored && (t = 1),
                this.insertChild(e, this.$el, t),
                this.layoutManager.positionGrid();
            },
            prependNewItems: function(e, t)
            {
                var n = this,
                    i = 0,
                    o = this.resource.copy();
                o.resetBookmark(),
                o.set("prepend", !0),
                o.set("page_size", e);
                var s = new h({
                    resource: o
                });
                this.children.length > 0 && this.children[0].options.anchored && (i = 1),
                s.options = this.options,
                s.render(function()
                {
                    _.each(s.children.reverse(),
                        function(e)
                        {
                            e.remove(),
                            n.insertChild(e, n.$el, i);
                        }),
                    n.layoutManager.positionGrid(),
                    t && t();
                });
            },
            requestMoreItems: function()
            {
                this.isReady() && this._requestMoreItems();
            },
            hasMoreItems: function()
            {
                return !this.resource.atEnd();
            },
            _triggerIfItemsEnd: function()
            {
                this.hasMoreItems() || this.triggerEvent(P.CONST.EVENT_ITEMS_END, null, !0);
            },
            setPageSize: function(e)
            {
                this.resource.set("page_size", e);
            },
            onAddedToDom: function()
            {
                this.resizeListener = this.listen(P.Viewport, P.CONST.EVENT_RESIZE, this.onResize),
                this.navigateListener = this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate),
                this._setUpGrid(),
                this.onResize();
            },
            onResize: function()
            {
                this.isReady() && this.layoutManager.resizeGrid();
            },
            hasItems: function()
            {
                return this.children.length > 0;
            },
            onContentReady: function()
            {
                var e = this.options.layout;
                if (e && "variable_height" !== e)
                {
                    if ("fixed_height" !== e)
                    {
                        return this.log.error('GridItems invalid value for "layout"', e),
                        void 0;
                    }
                    this.layoutManager = new c(this, this.options);
                }
                else
                {
                    this.layoutManager = new u(this, this.options);
                }
                this._setUpGrid(),
                this._triggerIfItemsEnd();
            },
            onRemovedFromDom: function()
            {
                this._scrollListener && (this.removeListener(this._scrollListener), this._scrollListener = null),
                this.stopPreventScroll(),
                this.navigateListener && this.removeListener(this.navigateListener),
                this.resizeListener && this.removeListener(this.resizeListener);
            },
            scrollToActiveItem: function(e)
            {
                var t = e.height(),
                    n = this.$(".activeItem"),
                    i = n.offset().top;
                e.scrollTop(i - t);
            },
            onChildContentChanged: function(e)
            {
                e.stopPropagation();
                var t = e.currentTarget;
                this.isReady() && (this.layoutManager.onChildContentChanged(t), this.rearrangeItems(!0));
            },
            onChildDimsChanged: function(e)
            {
                e.stopPropagation();
                var t = e.currentTarget;
                this.isReady() && this.layoutManager.onChildDimsChanged(t);
            },
            onChildRendered: function(e)
            {
                this.isReady() && this.layoutManager.onChildRendered(e);
            },
            onChildAdded: function(e)
            {
                var t = e.getParentElement();
                if (!t.hasClass("item"))
                {
                    var n = $("<div></div>").addClass("item");
                    n.insertBefore(e.getElement()),
                    n.append(e.getElement()),
                    t = n;
                }
                this.layoutManager && this.layoutManager.onChildAdded(e),
                this.sortManager && this.sortManager.onChildAdded(e);
            },
            onChildRemoved: function(e, t)
            {
                this.layoutManager && this.layoutManager.onChildRemoved(e, t);
            },
            empty: function()
            {
                this.isEmptying = !0,
                P.Module.prototype.empty.call(this),
                this.alreadyInitialized = !1,
                this.contentReady = !1,
                this.layoutManager && this.layoutManager.empty(),
                this.isEmptying = !1;
            },
            handleError: function(e)
            {
                this.pendingMoreRequest ? this.$(".errorMessage").remove() : P.Module.prototype.handleError.call(this, e);
            },
            _setUpGrid: function()
            {
                this._setScrollableElement(),
                this.isReady() && !this.alreadyInitialized && (this.layoutManager.positionGrid(), this.alreadyInitialized = !0);
            },
            _setScrollableElement: function()
            {
                this._scrollListener && (this.removeListener(this._scrollListener), this._scrollListener = null),
                this.scrollableElement = this.getScrollableElement(),
                this.options.scrollable && (this._scrollListener = this.listen(this.scrollableElement, "scroll", this._onScroll)),
                this._preventDefaultIfNeeded();
            },
            isReady: function()
            {
                return this.inDom && this.contentReady;
            },
            rearrangeItems: function()
            {
                this._requestMoreItemsIfNeeded(),
                this._hideAndShowItems();
            },
            _onScroll: function()
            {
                this.lastScrollTop = this.scrollTop,
                this.scrollTop = this.getScrollableElement().scrollTop(),
                this.rearrangeItems(!1);
            },
            _hideAndShowItems: function(e)
            {
                if (this.options.virtualize)
                {
                    e = e || !1;
                    var t = !this.lastScrollTop || this.scrollTop >= this.lastScrollTop ? r.DOWN : r.UP,
                        n = this.scrollTop - this.offsetFromScrollElement,
                        o = n + this.viewableHeight,
                        s = n - i,
                        a = o + i,
                        l = null === this.lastTopBorder || null === this.lastBottomBorder || n < this.lastTopBorder || o > this.lastBottomBorder;
                    (l || e) && (this.layoutManager.hideAndShowItems(e, this.pendingMoreRequest, t, s, a), this.lastTopBorder = s, this.lastBottomBorder = a),
                    e || this.scheduleHideShowItems();
                }
            },
            scheduleHideShowItems: _.debounce(function()
            {
                this._hideAndShowItems(!0);
            },
                n),
            onRendered: function()
            {
                this._requestMoreItemsIfNeeded();
            },
            _requestMoreItemsIfNeeded: function()
            {
                if (this.isReady() && this.options.scrollable && !this.pendingMoreRequest && !this.hasError && this.hasMoreItems())
                {
                    this.viewableHeight = this.scrollableElement.height(),
                    this.offsetFromScrollElement = this.$el.positionAncestor(this.scrollableElement).top;
                    var e = this.offsetFromScrollElement + this.layoutManager.getFilledHeight();
                    e - (this.viewableHeight + this.scrollTop) > 2 * this.viewableHeight || this._requestMoreItems();
                }
            },
            _requestMoreItems: function(e)
            {
                _.isUndefined(e) && (e = 2),
                this.triggerEvent(P.CONST.EVENT_ITEMS_REQUEST_START, null, !0),
                this.pendingMoreRequest = !0;
                var t = this,
                    n = this.renderAppend(function()
                    {
                        t.layoutManager.positionGridChildren(!0),
                        t.pendingMoreRequest = !1,
                        t.hasError && (t.triggerEvent(P.CONST.EVENT_ERROR_RESOLVED, null, !0), t.hasError = !1),
                        t.triggerEvent(P.CONST.EVENT_ITEMS_REQUEST_SUCCESS, null, !0),
                        t._requestMoreItemsIfNeeded(),
                        t._triggerIfItemsEnd();
                    },
                        function()
                        {
                            e > 0 ? t._requestMoreItems(e - 1) : (t.pendingMoreRequest = !1, t.hasError = !0, t.triggerEvent(P.CONST.EVENT_ERROR, null, !0), t._triggerIfItemsEnd()),
                            this.log.error("in grid append");
                        });
                return n || (t.pendingMoreRequest = !1),
                n;
            },
            _preventDefaultIfNeeded: function()
            {
                this.options.prevent_default_scroll && this.startPreventScroll(this.scrollableElement, this.$el);
            }
        });
        return h;
    }),
P.Module.define("GroupBoardEmailSettings", [],
    function()
    {
        return P.Module.extend({
            initialize: function()
            {
                this.childListen("change", this.onChildChange);
            },
            onSubmitValidated: function()
            {
                return this.save(),
                !1;
            },
            save: function()
            {
                var e = this,
                    t = {},
                    n = [];
                this.$form.find("input[name=collab_board_email]:checked").each(function()
                {
                    n.push(this.value);
                }),
                t.email_collaborative_board_ids = n;
                var i = this.getChildById("submitButton"),
                    o = new P.Resource("UserSettingsResource", t),
                    s = function(e)
                    {
                        e && !e.resource_response.error;
                    };
                i.showLoading(),
                o.call("update", {
                    success: s,
                    complete: function()
                    {
                        i.hideLoading(),
                        e.destroy();
                    }
                });
            },
            onContentReady: function()
            {
                var e = {};
                this.$form = this.$("form"),
                this.form = new P.Form(this.$form, e),
                this.listen(this.form, "submitValidated", this.onSubmitValidated);
            },
            onChildChange: function(e)
            {
                var t = e.target;
                if ("toggleAll" === t.id)
                {
                    var n;
                    n = t.isChecked() ?
                        function(e)
                        {
                            e.setChecked(!0);
                        } : function(e)
                        {
                            e.setChecked(!1);
                        };
                    var i = this.getChildrenByModuleName("ui.Checkbox");
                    _.each(i, n);
                }
            }
        });
    }),
P.Module.define("Header", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .exploreIcon": "onExploreIconClick"
            },
            onExploreIconClick: function()
            {
                var e = new P.Resource("UserRecommendedBoardResource");
                e.call("get", {
                    success: function(e)
                    {
                        var t = e.resource_response.data.url;
                        P.navigate(t);
                    }
                });
            },
            getUserMenu: function()
            {
                return this.getChildById("userMenu");
            },
            getLogo: function()
            {
                return this.$(".logo");
            }
        });
    }),
P.Module.define("HomePage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            showsFollowingFeed: function()
            {
                return this.getChildById("authHome").showsFollowingFeed();
            }
        });
    }),
P.Module.define("IframeEmbed", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("ImagesFeedPage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.getChildById("domainPinsGrid");
                e && 0 === e.children.length ? e.destroy() : this.$(".domainPinsHolder").css("visibility", "visible");
            }
        });
    }),
P.Module.define("IncrementingNavigateButton", ["NavigateButton"],
    function(e)
    {
        var t = "hidden";
        return e.extend({
            onContentReady: function()
            {
                this.listen(this, P.CONST.EVENT_INCREMENT_BUTTON_CREATE, this.makeVisible),
                this.listen(this, P.CONST.EVENT_INCREMENT_BUTTON_DESTROY, this.makeInvisible);
            },
            getValue: function()
            {
                if (this.extraData && this.extraData.actionCount)
                {
                    return this.extraData.actionCount;
                }
                var e = $.trim(this.$el.text()),
                    t = parseInt(e, 10);
                return t;
            },
            setValue: function(e)
            {
                this.extraData.actionCount = e,
                this.$el.text(e);
            },
            isHidden: function()
            {
                return this.$el.hasClass(t);
            },
            makeVisible: function()
            {
                var e = this.isHidden();
                e && this.$el.removeClass(t);
            },
            makeInvisible: function()
            {
                var e = this.isHidden();
                e || this.$el.addClass(t);
            },
            increment: function()
            {
                var e = this,
                    t = this.getValue();
                isNaN(t) && (t = 0),
                this.triggerEvent(P.CONST.EVENT_INCREMENT_BUTTON_CREATE, e.options.siblingButtonId, !0),
                t += 1,
                this.setValue(t);
            },
            decrement: function()
            {
                var e = this,
                    t = this.getValue();
                return t -= 1,
                0 === t ? (this.triggerEvent(P.CONST.EVENT_INCREMENT_BUTTON_DESTROY, e.options.siblingButtonId, !0), void 0) : (this.setValue(t), void 0);
            }
        });
    }),
P.Module.define("InfoBarBase", [],
    function()
    {
        var e = "active";
        return P.Module.extend({
            onContentReady: function()
            {
                this.listen(this, P.CONST.EVENT_NAVIGATE, this.onTabClick);
            },
            onTabClick: function(e)
            {
                e.data.$el && this.selectTab(e.data.$el.attr("href"));
            },
            selectTab: function(t)
            {
                this.$("a").each(function()
                {
                    var n = $(this);
                    n.attr("href") === t ? n.addClass(e) : n.removeClass(e);
                });
            }
        });
    }),
P.Module.define("InlineHoverButton", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("InterestFeedPage", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("InviteFriendsRep", [],
    function()
    {
        return P.Module.extend({
            events: {
                click: "onClick"
            },
            onClick: function()
            {
                return "facebook" === this.options.network && P.FacebookDialog.open({
                    type: "send",
                    name: this.extraData.name,
                    description: this.extraData.description,
                    path: "/",
                    picture: this.extraData.picture
                }),
                !1;
            }
        });
    }),
P.Module.define("LanguageDropdown", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .language": "onClick"
            },
            onClick: function(e)
            {
                var t = $(e.currentTarget),
                    n = t.attr("data-url");
                return P.navigate(n),
                !1;
            }
        });
    }),
P.Module.define("LanguageMenu", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("List", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("Login", [],
    function()
    {
        var e = 85;
        return P.Module.extend({
            events: {},
            setupForm: function()
            {
                this.$form = this.$("form"),
                this.form = new P.Form(this.$form, {
                    username_or_email: [P.Validator.Required(), P.Validator.Email()],
                    password: [P.Validator.Required()]
                });
            },
            onContentReady: function()
            {
                var e = {},
                    t = this.options.invite_follow_board,
                    n = this.options.invite_follow_user;
                return n && (t ? e.invite_follow_board = n + "/" + t : e.invite_follow_user = n, P.SessionStorage.setItem(P.CONST.SESSION_KEY_INVITE_FOLLOW, e)),
                P.currentUser.isAuthenticated() ? (this.redirect(e), void 0) : (this.setupForm(), this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated), this.getChildById("emailSignup") && this.listen(this.getChildById("emailSignup"), P.CONST.EVENT_BUTTON_CLICK, this.onEmailSignup), this.getChildById("facebookSignup") && this.listen(this.getChildById("facebookSignup"), P.CONST.EVENT_BUTTON_CLICK, this.onFacebookSignup), this.getChildById("facebookLogin") && this.listen(this.getChildById("facebookLogin"), P.CONST.EVENT_BUTTON_CLICK, this.onFacebookLogin), this.getChildById("twitterLogin") && this.listen(this.getChildById("twitterLogin"), P.CONST.EVENT_BUTTON_CLICK, this.onTwitterConnect), void 0);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.login({
                    username_or_email: this.form.getValue("username_or_email"),
                    password: this.form.getValue("password")
                });
            },
            onTwitterConnect: function(e)
            {
                e.stopPropagation(),
                this.connect(P.SocialConnect.TWITTER, this.onTwitterConnectSuccess);
            },
            onEmailSignup: function()
            {
                P.trackRegisterAction("register_email");
            },
            onFacebookSignup: function(e)
            {
                e.stopPropagation(),
                P.trackRegisterAction("register_facebook_attempt"),
                this.facebookConnect();
            },
            onFacebookLogin: function(e)
            {
                e.stopPropagation(),
                this.facebookConnect();
            },
            facebookConnect: function()
            {
                this.connect(P.SocialConnect.FACEBOOK, this.onFacebookConnectSuccess);
            },
            onTwitterConnectSuccess: function(e)
            {
                this.login({
                    twitter_id: e.id,
                    twitter_token: e.oauth_token,
                    twitter_token_secret: e.oauth_secret
                });
            },
            onFacebookConnectSuccess: function(e)
            {
                var t = P.NOOP;
                this.options.register && (t = function()
                {
                    return P.navigate("/join/register/facebook/");
                }),
                this.login({
                        facebook_id: e.id,
                        facebook_token: e.access_token
                    },
                    t);
            },
            connect: function(e, t)
            {
                var n = P.SocialConnect.instance(),
                    i = this;
                return n.connect(e, {
                    success: function(e)
                    {
                        t.call(i, e);
                    },
                    error: function()
                    {
                        P.showError(P.string("connectError"));
                    }
                }),
                !1;
            },
            login: function(t, n)
            {
                var i = this.getChildById("loginButton"),
                    o = P.SessionStorage.getItem(P.CONST.SESSION_KEY_INVITE_FOLLOW),
                    s = this,
                    r = function()
                    {
                        s.showLoading(!0),
                        s.redirect(o);
                    };
                n || (n = function(n)
                {
                    if (s.showError(n.message), n.api_error_code === e && t.username_or_email)
                    {
                        var i = P.getResetPasswordOneClickUrl({
                            username_or_email: t.username_or_email
                        });
                        s.navigate(i);
                    }
                });
                var a = function()
                {
                    i && i.hideLoading();
                };
                P.currentUser.login(t, r, n, a);
            },
            redirect: function(e)
            {
                var t = "/";
                e && (e.invite_follow_user ? t = "/" + e.invite_follow_user + "/" : e.invite_follow_board && (t = "/" + e.invite_follow_board + "/"), P.SessionStorage.removeItem(P.CONST.SESSION_KEY_INVITE_FOLLOW));
                var n = this.options.next || t;
                P.isLocalUrl(n) || (n = "/"),
                window.location.href = n;
            },
            showError: function(e)
            {
                this.$(".loginError").html("<p>" + e + "</p>").show();
            }
        });
    }),
P.Module.define("LoginButton", ["NavigateButton"],
    function(e)
    {
        return e.extend({
            getNavigateUrl: function()
            {
                var e = P.normalizeUrl(window.location.href),
                    t = "/login/";
                return e && (t += "?" + $.param({
                    next: e
                })),
                t;
            }
        });
    }),
P.Module.define("LoginPage", [],
    function()
    {
        var e = 50;
        return P.Module.extend({
            events: {},
            resizeWindow: function()
            {
                var t = this.getChildByModuleName("Login").$el.height(),
                    n = P.Viewport.height,
                    i = P.Viewport.width;
                n < t && window.resizeTo(i + e, t + e);
            },
            onContentReady: function()
            {
                this.resizeWindow();
            }
        });
    }),
P.Module.define("LogoutPage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.logout();
            },
            logout: function()
            {
                var e = new P.Resource("UserSessionResource", {});
                e.call("delete", {
                    success: function()
                    {
                        P.SessionStorage.clear(),
                        P.LocalStorage.clear(),
                        Cookie.unset(P.CONST.COOKIE_USE_DENZEL),
                        Cookie.unset(P.CONST.COOKIE_SHOW_WELCOME),
                        Cookie.unset(P.CONST.COOKIE_NAG_LANGUAGE),
                        P.currentUser.logout(function()
                        {
                            window.location.href = "/";
                        });
                    }
                });
            }
        });
    }),
P.Module.define("Modal", ["PositionModule"],
    function(e)
    {
        var t = "show",
            n = e.extend({
                events: {
                    "click .modalMask": "onClick",
                    "click .modalContainer": "onModalContainerClick"
                },
                positionMode: P.CONST.PositionMode.VIEWPORT_MIDDLE,
                initialize: function()
                {
                    e.prototype.initialize.apply(this),
                    this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onChildButtonClick);
                },
                render: function(e)
                {
                    this.empty();
                    var t = this.options.mask_type || "",
                        n = this.options.container_class || "";
                    this.$el.append('<div class="modalMask ' + t + '"></div>' + '<div class="modalContainer ' + n + '">' + '<span class="positionModuleCaret"></span>' + '<div class="modalContent">' + '<div class="modalModule"></div>' + "</div>" + "</div>"),
                    this.getCanDismiss() && (this.$(".modalContent").append("<button class='Button closeModal inModal cancelButton borderless'><em></em>&nbsp;</button>"), this.$(".closeModal").on("click", _.bind(this.destroy, this)));
                    var i = this.getModule();
                    i && this.addModuleToContainer(i),
                    e && e.call(this);
                },
                addModuleToContainer: function(e)
                {
                    var t = this;
                    e.id = "modalModule",
                    e.errorStrategy = P.CONST.ErrorStrategy.SHOW,
                    this.insertChild(e, this.getModuleContainer()),
                    e.contentReady ? this.setupModule(e) : e.render(P.stopwatch.wrapContinuation("Modal.addModuleToContainer success",
                            function()
                            {
                                t.setupModule(e);
                            }), P.stopwatch.wrapContinuation("Modal.addModuleToContainer failed",
                                function()
                                {
                                    P.showError(P.string("errorMessage")),
                                    t.hide();
                                }));
                },
                onChildRendered: function(e)
                {
                    this.setupModule(e);
                },
                setupModule: function(e)
                {
                    e.setModal(this),
                    this.onRendered(),
                    this.onContentReady();
                },
                show: function()
                {
                    this.render(P.stopwatch.wrapContinuation("Modal:show continuation",
                        function()
                        {
                            P.log("success");
                        }));
                },
                hide: function()
                {
                    this.destroy();
                },
                onAddedToDom: function()
                {
                    P.Body.pushScrolling(!1);
                },
                onRemovedFromDom: function()
                {
                    P.Body.pop();
                },
                getModule: function()
                {
                    return this.options.module;
                },
                setTransparentContent: function(e)
                {
                    this.getContent().toggleClass("transparent", e),
                    this.$(".closeModal").toggle(!e);
                },
                getContent: function()
                {
                    return this.$(".modalContent");
                },
                getModuleContainer: function()
                {
                    return this.$(".modalModule");
                },
                getFullName: function()
                {
                    var e = P.Module.prototype.getFullName.call(this);
                    return this.moduleOpener && (e = this.moduleOpener.getFullName() + "#" + e),
                    e;
                },
                getPositionElement: function()
                {
                    return this.$(".modalContainer");
                },
                setModule: function(e)
                {
                    var t = this.getChildById("modalModule");
                    t && (t.id = "", t.remove()),
                    this.options.module = e,
                    t = this.$(".modalModule"),
                    t.empty(),
                    this.addModuleToContainer(e);
                },
                onChildRemoved: function()
                {
                    this.getChildById("modalModule") || this.hide();
                },
                onChildButtonClick: function(e)
                {
                    var t = e.target;
                    if (t && t.isCancelButton())
                    {
                        var n = this.options.module,
                            i = n.GACategory;
                        i || (i = n.options.ga_category),
                        i && P.trackGAEvent(i, P.CONST.GA_ACTION_CLICK_CANCEL),
                        e.stopPropagation(),
                        this.hide();
                    }
                },
                onClick: function()
                {
                    this.getCanDismiss() && this.hide();
                },
                onModalContainerClick: function(e)
                {
                    e.target === e.currentTarget && (e.stopPropagation(), this.onClick());
                },
                onRendered: function()
                {
                    this.positionModule();
                    var e = this.$el;
                    e.addClass(t),
                    this.options.transparent && this.setTransparentContent(!0);
                },
                getCanDismiss: function()
                {
                    var e = this.options.can_dismiss;
                    return void 0 === e || e;
                }
            });
        return P.stopwatch.wrapMethods(n.prototype, "Modal", ["render", "addModuleToContainer", "setModule", "show"]),
        n;
    }),
P.Module.define("ModalTrigger", [],
    function()
    {
        var e = P.Module.extend({
            showModal: function()
            {
                this.options.ga_category && P.trackGAEvent(this.options.ga_category, P.CONST.GA_ACTION_OPEN_MODAL);
                var e = this;
                this.showLoading(),
                P.loadModule(this.options.submodule, P.stopwatch.wrapContinuation("P.loadModule continuation",
                    function(t)
                    {
                        e.hideLoading(),
                        e.showInModal(t, e.options.extra_options);
                    }));
            }
        });
        return P.stopwatch.wrapMethods(e.prototype, "ModalTrigger", ["showModal"]),
        e;
    }),
P.Module.define("NagBase", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .nagClose": "onCloseButtonClick"
            },
            clickHandler: function()
            {
                return null;
            },
            onCloseButtonClick: function()
            {
                this.destroy(),
                P.trackGAEvent("nag", P.CONST.GA_ACTION_CLICK_CLOSE, "type", this.extraData.type);
            },
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_USER_UPDATED] = this.onActionSaved,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, e);
            },
            onActionSaved: function(e, t, n)
            {
                this.$(".message").text(n);
            },
            resourceCall: function(e, t, n)
            {
                var i = n.success,
                    o = n.error;
                this.xhr = $.ajax({
                    cache: !1,
                    url: e,
                    data: {},
                    dataType: "json",
                    type: "get" === t ? "get" : "post",
                    success: i,
                    error: o
                });
            }
        });
    }),
P.Module.define("NagEmail", ["NagBase"],
    function(e)
    {
        return e.extend({
            events: {
                "click .editEmail": "clickHandler",
                "click .resendEmail": "clickHandler"
            },
            clickHandler: function(e)
            {
                return "editEmail" === e.target.className ? this.updateEmail() : this.resendEmail(),
                !1;
            },
            onActionSaved: function(t, n, i)
            {
                i === P.CONST.PUBSUB_MESSAGE_USER_EMAIL_UPDATED ? this.resendEmail() : e.prototype.onActionSaved.apply(this, arguments);
            },
            updateEmail: function()
            {
                var e = "email_verification" === this.extraData.type,
                    t = this;
                this.showLoading();
                var n = {
                    name: "UserEditEmail",
                    options: {
                        sendVerifyEmail: e
                    },
                    resource: {
                        name: "UserSettingsResource"
                    }
                };
                P.loadModule(n,
                    function(e)
                    {
                        t.hideLoading(),
                        t.showInModal(e);
                    });
            },
            resendEmail: function()
            {
                var e = function(e)
                {
                    var t;
                    e.error && (t = e.error),
                    t = "success" === e.status ? P.string("resendConfirmationEmailSuccess") : "nothingtodo" === e.status ? P.string("resendConfirmationEmailNoOp") : e.message,
                    P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_USER_UPDATED, t);
                },
                    t = function(e)
                    {
                        P.log(e);
                    };
                return this.resourceCall("/verify_email/resend/", "post", {
                    success: e,
                    error: t
                }),
                !1;
            }
        });
    }),
P.Module.define("NagPolicy", ["NagBase"],
    function(e)
    {
        return e.extend({
            events: {
                "click .policy": "clickHandler"
            },
            clickHandler: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "pin_policy"
                        }
                    };
                return P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM,
                            function()
                            {
                                e.savePolicyConfirmation();
                            });
                    }),
                !1;
            },
            onActionSaved: function()
            {
                e.prototype.onActionSaved.apply(this, arguments);
                var t = this;
                setTimeout(function()
                {
                    t.parent.render();
                },
                    2e3);
            },
            savePolicyConfirmation: function()
            {
                var e = function(e)
                {
                    "success" === e.status ? P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_USER_UPDATED, "Thanks for confirming!") : P.log(e);
                },
                    t = function(e)
                    {
                        P.log(e);
                    };
                this.resourceCall("/confirm_guidelines/", "post", {
                    success: e,
                    error: t
                });
            }
        });
    }),
P.Module.define("NagSearch", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("NagSecurity", ["NagBase"],
    function(e)
    {
        return e.extend({
            events: {
                "click .resetPassword": "clickHandler"
            },
            clickHandler: function()
            {
                var e = "/password/reset/";
                return P.changeWindowLocation(e),
                !1;
            }
        });
    }),
P.Module.define("NagUnauth", ["NagBase"],
    function(e)
    {
        return e.extend({
            events: {},
            onContentReady: function()
            {
                var e = this;
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onNavigateButtonClick),
                P.e.duf && P.FBEnsureInit(function()
                {
                    P.FB.getLoginStatus(function(t)
                    {
                        ("connected" === t.status || "not_authorized" === t.status) && e.$(".facepileWrapper").removeClass("hidden");
                    });
                });
            },
            onNavigateButtonClick: function(e)
            {
                var t = e.target;
                "join" === t.id && P.trackRegisterAction("register_from_nag");
            }
        });
    }),
P.Module.define("Nags", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("NavigateButton", ["Button"],
    function(e)
    {
        return e.extend({
            getNavigateUrl: function()
            {
                return this.options.url;
            },
            onClick: function(t)
            {
                this.options.ga_category && P.trackGAEvent(this.options.ga_category, P.CONST.GA_ACTION_CLICK),
                t.stopPropagation(),
                t.preventDefault();
                var n = this.getNavigateUrl();
                e.prototype.onClick.call(this),
                this.options.safe_link ? P.SafeLink.open(n, this.options.safe_link_pin_id) : this.navigate(n, null, this.options.force_refresh);
            }
        });
    }),
P.Module.define("NewPinsIndicator", [],
    function()
    {
        return P.Module.extend({
            events: {
                click: "onClick"
            },
            render: function(e)
            {
                var t = P.string("oneNewPin");
                this.options.count && (1 !== this.options.count && (t = this.options.count + " " + P.string("newPins")), this.$el.text(t), this.$el.append('<em class="arrows"></em>')),
                P.e.npsb && this.$el.addClass("biggie"),
                this.onContentReady(),
                this.onRendered(),
                e && e();
            },
            onClick: function()
            {
                this.triggerEvent("click", null, !0);
            }
        });
    }),
P.Module.define("NotificationItems", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("NotificationSettings", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.$form = this.$("form");
                var e = new P.Form(this.$form);
                this.listen(e, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function()
            {
                var e = this;
                this.$form.serializeArray();
                var t = {},
                    n = {};
                this.$(".pushNotifSettings input[type=checkbox]").each(function()
                {
                    var e = $(this),
                        t = e.attr("name");
                    n[t.substr(5)] = e.is(":checked") ? "anyone" : "none";
                }),
                t.push_settings = JSON.stringify(n),
                t.filter_settings = this.$("input[name=filter_settings]:checked").val();
                var i = new P.Resource("NotificationSettingsResource", t);
                return this.showLoading(!0),
                i.call("update", {
                    complete: function()
                    {
                        e.hideLoading();
                    },
                    success: function()
                    {
                        e.destroy();
                    }
                }),
                !1;
            }
        });
    }),
P.Module.define("Notifications", [],
    function()
    {
        var e = "data-actor-id",
            t = 300;
        return P.Module.extend({
            events: {
                "mouseover .notifMessage a": "onActorMouseover",
                "click .notifItem": "onNotificationClick",
                "click .notifSettings": "onSettingsClick"
            },
            mixins: [P.Mixins.PreventScroll],
            initialize: function()
            {
                _.bindAll(this, "onNotificationsScroll"),
                this.onNotificationsScroll = _.throttle(this.onNotificationsScroll, 200);
            },
            onContentReady: function()
            {
                this.scrollableElement = this.$(".notifContent"),
                this._scrollListener = this.listen(this.scrollableElement, "scroll", this.onNotificationsScroll),
                this.startPreventScroll(this.scrollableElement, this.$(".NotificationItems")),
                this.listen(this.parent, P.CONST.EVENT_DROPDOWN_HIDE, this.onHide);
            },
            onHide: function()
            {
                this.$(".unseen").removeClass("unseen");
            },
            onSettingsClick: function()
            {
                var e = this,
                    t = {
                        name: "NotificationSettings",
                        resource: {
                            name: "NotificationSettingsResource",
                            options: {}
                        }
                    };
                return P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t);
                    }),
                !1;
            },
            onActorMouseover: function(t)
            {
                var n = $(t.target);
                n.attr(e),
                this.setActiveUser(n.attr(e), n.parents(".notifItem"));
            },
            onNotificationClick: function(e)
            {
                var t = $(e.target),
                    n = $(e.currentTarget),
                    i = n.attr("data-url");
                return t.is("a") ? !0 : (i && this.navigate(i), void 0);
            },
            onNotificationsScroll: function()
            {
                if (!this.rendering)
                {
                    var e = this.$(".NotificationItems"),
                        n = e.height() + e.position().top - this.scrollableElement.height();
                    return n <= t && this.fetchMore(),
                    !1;
                }
            },
            fetchMore: function()
            {
                if (!this.rendering)
                {
                    if (this.resource.atEnd())
                    {
                        return this.removeListener(this._scrollListener),
                        void 0;
                    }
                    var e = this;
                    this.rendering = !0,
                    this.getChildById("items").renderAppend(function()
                    {
                        e.rendering = !1;
                    });
                }
            },
            setActiveUser: function(t, n)
            {
                n.find(".actorImage, .notifComment").each(function()
                {
                    var n = $(this);
                    n.toggleClass("active", n.attr(e) === t);
                });
            }
        });
    }),
P.Module.define("NotificationsButton", ["DropdownButton"],
    function(e)
    {
        return e.extend({
            getDropdownModule: function()
            {
                return this.getNotificationsModule();
            },
            getNotificationsModule: function()
            {
                var e = Math.max(this.unseenCount || 10, 20);
                return {
                    name: "Notifications",
                    resource: {
                        name: "NotificationsResource",
                        options: {
                            count: e
                        }
                    }
                };
            },
            onContentReady: function()
            {
                e.prototype.onContentReady.call(this),
                this.data && this.setBadge(this.data),
                this.childListen(P.CONST.EVENT_DROPDOWN_HIDE, this.onDropdownHide),
                this.childListen(P.CONST.EVENT_DROPDOWN_SHOW, this.onDropdownShow),
                this.listen(P.Updater.instance(), "notifications_count",
                    function(e)
                    {
                        this.setBadge(e);
                    });
            },
            onDropdownHide: function()
            {
                if (this.shouldClearDropdown)
                {
                    var e = this.getDropdown();
                    e && e.empty();
                }
                this.shouldClearDropdown = !1,
                this.setActiveStyle(!1);
            },
            onDropdownShow: function()
            {
                this.setBadge(0);
            },
            setBadge: function(e)
            {
                if (!this.$badge)
                {
                    this.$badge = $('<div class="badge"></div>');
                    var t = this.getChildByModuleName("Button");
                    t.$el.append(this.$badge);
                }
                e && (this.$badge.text(e), this.clearDropdown()),
                this.unseenCount = e,
                this.$el.toggleClass("hasCount", !!e);
            },
            clearDropdown: function()
            {
                var e = this.getDropdown();
                e && (e.isVisible() ? this.shouldClearDropdown = !0 : e.empty());
            }
        });
    }),
P.Module.define("OffsitePage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                if (!P.SafeLink.validateToken(this.options.token))
                {
                    return P.showError(P.string("offsiteInvalidToken")),
                    void 0;
                }
                var e = this.options.url,
                    t = this.options.pin_id;
                P.SafeLink.checkLink(e, {
                    pin_id: t,
                    proceed: function(e)
                    {
                        window.location.replace(e.url);
                    },
                    cancel: function()
                    {
                        window.close();
                    }
                });
            }
        });
    }),
P.Module.define("PaddedPin", [],
    function()
    {
        var e = "visible",
            t = "editButton";
        return P.Module.extend({
            events: {
                "mouseenter .pinImageSourceWrapper": "onMouseEnter"
            },
            onContentReady: function()
            {
                var e = this;
                if (!this._hoverIntent)
                {
                    var t = this.$(".pinImageSourceWrapper");
                    this._hoverIntent = new P.HoverIntent(t, {
                        exitDelay: 200
                    });
                }
                this.listen(this._hoverIntent, P.CONST.EVENT_HOVERINTENT_OUT_COMPLETE,
                    function()
                    {
                        e.onMouseOutComplete();
                    });
            },
            getEditButton: function()
            {
                return this.getChildById(t);
            },
            onMouseEnter: function()
            {
                var t = this.$(".sourceFlagWrapper");
                this.$sourceFlagWrapper || (this.$sourceFlagWrapper = t),
                this.$sourceFlagWrapper.addClass(e);
            },
            onMouseOutComplete: function()
            {
                this.$sourceFlagWrapper && this.$sourceFlagWrapper.removeClass(e);
            }
        });
    }),
P.Module.define("PagedGrid", [],
    function()
    {
        var e = 9,
            t = "hide";
        return P.Module.extend({
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onMoreItemsClick);
            },
            onAddedToDom: function()
            {
                this.contentReady && this._setUpGrid();
            },
            onContentReady: function()
            {
                this.inDom && this._setUpGrid();
            },
            prependChildItem: function(e)
            {
                var t = this.getChildById("grid");
                t.prependChildItem(e);
            },
            onMoreItemsClick: function(e)
            {
                var t = e.target;
                t && "moreItems" === t.id && (e.stopPropagation(), this.requestMore());
            },
            _setUpGrid: function()
            {
                var n = this.getChildById("grid"),
                    i = this.options.ajax_page_size || e;
                n.setPageSize(i),
                n.hasMoreItems() || this.$(".moreItems").addClass(t),
                this.childListen(P.CONST.EVENT_CONTENT_CHANGED, this.onChildContentChanged),
                this.childListen(P.CONST.EVENT_ERROR, this.onChildError);
            },
            hasItems: function()
            {
                var e = this.getChildById("grid");
                return e.hasItems();
            },
            requestMore: function()
            {
                if (this.contentReady)
                {
                    var e = this.getChildById("moreItems");
                    e.showLoading();
                    var t = this.getChildById("grid");
                    t.requestMoreItems();
                }
            },
            onChildContentChanged: function()
            {
                var e = this.getChildById("moreItems");
                if (e)
                {
                    if (this.gridHasError)
                    {
                        return e.hide(),
                        this.gridHasError = !1,
                        void 0;
                    }
                    var t = this.getChildById("grid");
                    t.hasMoreItems() ? (e.show(), e.hideLoading()) : e.destroy();
                }
            },
            onChildError: function(e)
            {
                P.log("Child error!", e),
                e.target === this.getChildById("grid") && (this.gridHasError = !0);
            }
        });
    }),
P.Module.define("PasswordResetOneClick", [],
    function()
    {
        return P.Module.extend({
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onResetPassword);
            },
            onSuccess: function()
            {
                this.$(".message").hide(),
                this.$(".successMessage").show();
            },
            onResetPassword: function()
            {
                var e = {
                    username_or_email: this.options.username_or_email
                },
                    t = new P.Resource("UserResetPasswordResource", e),
                    n = this.getChildById("resetPasswordButton");
                n.showLoading(),
                t.call("create", {
                    success: this.onSuccess,
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("Pillow", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("Pin", [],
    function()
    {
        var e = "PaddedPin",
            t = "editButton",
            n = {
                DETAILED: "detailed",
                SUMMARY: "summary"
            };
        return P.Module.extend({
            events: {
                mouseleave: "onPinMouseout"
            },
            onPinMouseout: function()
            {
                var e = this.getChildById("sendPinButton");
                if (e)
                {
                    var t = e.getDropdown();
                    t && t.isVisible() && this.toggleRepinLikeWrapper(!0);
                }
            },
            toggleRepinLikeWrapper: function(e)
            {
                this.$(".repinLikeWrapper").toggleClass("visible", e);
            },
            onButtonClick: function(e)
            {
                "expandGiraffe" === e.target.options.class_name && (this.onExpandGiraffeClick(e), e.target.$el.remove());
            },
            onExpandGiraffeClick: function()
            {
                this.$(".pinImageWrapper").removeClass("collapsed"),
                this.triggerEvent(P.CONST.EVENT_DIMS_CHANGED, null, !0);
            },
            showEditModal: function()
            {
                var i;
                return i = this.options.view_type === n.DETAILED ? this.getChildByModuleName(e).getEditButton() : this.getChildById(t),
                i ? (i.showModal(), !0) : !1;
            },
            getPinMedia: function()
            {
                var e = this._getViewType();
                switch (e)
                {
                    case "detailed":
                        return this.data.embed && this.data.embed.src ? this.$("iframe") : this.$(".PaddedPin img.pinImage");
                    case "boardPinsGrid":
                        return this.$("img");
                    case "summary":
                        return this.$(".pinHolder .pinImg");
                    default:
                        return this.log.error("requesting pin media for unsupported view_type:" + e),
                        null;
                }
            },
            getPinId: function()
            {
                return this.resource.get("id");
            },
            isEmbed: function()
            {
                return this.data.embed && this.data.embed.src;
            },
            getDetailedImageDimensions: function()
            {
                var e = {
                    width: 600,
                    height: 300
                },
                    t = {
                        youtube: e,
                        vimeo: e,
                        soundcloud: {
                            width: 553,
                            height: 166
                        }
                    };
                if (this.data.is_playable && (this.data.is_video || this.data.attribution && this.data.attribution.embed))
                {
                    if (this.data.attribution)
                    {
                        var n = t[this.data.attribution.provider_name];
                        if (n)
                        {
                            return n;
                        }
                    }
                    if (this.data.embed)
                    {
                        return this.data.embed;
                    }
                }
                return this.data.images["736x"];
            },
            _getViewType: function()
            {
                return this.options.view_type ? this.options.view_type : n.SUMMARY;
            },
            onContentReady: function()
            {
                var e = this.options.pin_id;
                if (e)
                {
                    var t = {};
                    t[P.CONST.PUBSUB_TOPIC_PIN_COMMENT_CREATED] = this.onPinCommentCreated,
                    t[P.CONST.PUBSUB_TOPIC_PIN_DELETED] = this.onPinDeleted,
                    t[P.CONST.PUBSUB_TOPIC_PIN_LIKED] = this.onPinLiked,
                    t[P.CONST.PUBSUB_TOPIC_PIN_UNLIKED] = this.onPinUnliked,
                    t[P.CONST.PUBSUB_TOPIC_PIN_UPDATED] = this.onPinUpdated,
                    this.pubsubSubscribe(e, t);
                }
                this.listen(this, P.CONST.EVENT_NAVIGATE, this.onNavigate),
                this.childListen(P.CONST.EVENT_NAVIGATE, this.onNavigate),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick),
                this.childListen(P.CONST.EVENT_DROPDOWN_SHOW, this.onDropdownShow),
                this.childListen(P.CONST.EVENT_DROPDOWN_HIDE, this.onDropdownHide),
                this.childListen(P.CONST.EVENT_LAZY_IMAGE_COMPLETE, this.onImageLoaded);
            },
            onDropdownShow: function()
            {
                this.toggleRepinLikeWrapper(!0);
            },
            onDropdownHide: function()
            {
                this.toggleRepinLikeWrapper(!1);
            },
            onImageLoaded: function(e)
            {
                e.stopPropagation();
                var t = this.$(".fadeContainer");
                if (t.length > 0)
                {
                    var n = P.Viewport.isOverlapping(t, 0);
                    P.deferDomManipulation(function()
                    {
                        t.addClass("loaded"),
                        n && t.addClass("fade");
                    });
                }
            },
            onNavigate: function(e)
            {
                if (this.options.view_type === n.DETAILED && P.isOffsiteUrl(e.data.url))
                {
                    e.stopPropagation();
                    var t = this.options.pin_id,
                        i = e.data.url;
                    P.SafeLink.open(i, t);
                }
            },
            onPinCommentCreated: function()
            {
                this.getChildById("commentList") || this.render();
            },
            onPinLiked: function()
            {
                this.triggerEvent(P.CONST.EVENT_PIN_LIKED, null, !0);
                var e = this.getChildById("likeButton");
                e && e.setState(!0);
            },
            onPinUnliked: function()
            {
                this.triggerEvent(P.CONST.EVENT_PIN_UNLIKED, null, !0);
                var e = this.getChildById("likeButton");
                e && e.setState(!1);
            },
            onPinUpdated: function(e, t, n)
            {
                this.triggerEvent(P.CONST.EVENT_PIN_UPDATED, n, !0),
                this.render();
            },
            onPinDeleted: function()
            {
                this.destroy();
            }
        });
    }),
P.Module.define("PinActionBar", [],
    function()
    {
        var e = "leftRounded",
            t = "likesButton",
            n = "repinsButton",
            i = "pinItButton";
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.options.pin_id;
                if (e)
                {
                    var t = {};
                    t[P.CONST.PUBSUB_TOPIC_PIN_LIKED] = this.onPinLiked,
                    t[P.CONST.PUBSUB_TOPIC_PIN_UNLIKED] = this.onPinUnliked,
                    this.pubsubSubscribe(e, t);
                }
                var n = {};
                n[P.CONST.PUBSUB_TOPIC_PIN_CREATED] = this.onPinRepinned,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, n),
                this.childListen(P.CONST.EVENT_INCREMENT_BUTTON_DESTROY, this.onCloseupIncrementButtonHide),
                this.childListen(P.CONST.EVENT_INCREMENT_BUTTON_CREATE, this.onCloseupIncrementButtonShow);
            },
            removeDropdowns: function()
            {
                var e = this.getDropdowns();
                _.each(e,
                    function(e)
                    {
                        e.hide();
                    });
            },
            getDropdowns: function()
            {
                var e = this.getChildrenByModuleName("DropdownButton"),
                    t = [];
                return _.map(e,
                    function(e)
                    {
                        var n = e.getDropdown();
                        t.push(n);
                    }),
                t;
            },
            showRepinModal: function()
            {
                var e = this.getChildById(i);
                e.showModal();
            },
            getLoadingSpinnerOptions: function()
            {
                return null;
            },
            onPinRepinned: function(e, t, i)
            {
                var o = this.getChildById(n);
                i.board && "secret" !== i.board.privacy && o && o.increment();
            },
            onPinLiked: function()
            {
                var e = this.getChildById(t);
                e && e.increment();
            },
            onPinUnliked: function()
            {
                var e = this.getChildById(t);
                e && e.decrement();
            },
            onCloseupIncrementButtonHide: function(t)
            {
                var n = t.data,
                    i = this.getChildById(n);
                i.$el.removeClass(e);
            },
            onCloseupIncrementButtonShow: function(t)
            {
                var n = t.data,
                    i = this.getChildById(n);
                i.$el.addClass(e);
            },
            setDropdownsFixed: function(e)
            {
                var t = this.getDropdowns();
                _.each(t,
                    function(t)
                    {
                        var n = _.clone(t.options);
                        n.fixed = e,
                        t.setOptions(n),
                        t.positionModule();
                    });
            },
            updateSticky: function(e)
            {
                this._sticky || (this._sticky = new P.Sticky(this.$el, e), this.listen(this._sticky, P.CONST.EVENT_STICKY_FIXED,
                    function(e)
                    {
                        this.setDropdownsFixed(e);
                    }));
            },
            unsticky: function()
            {
                this._sticky && this._sticky.unSticky();
            }
        });
    }),
P.Module.define("PinBookmarklet", [],
    function()
    {
        return P.Module.extend({
            events: {},
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate);
            },
            onContentReady: function()
            {
                this.resizeWindowToFit();
            },
            onChildRemoved: function()
            {
                this.children.length ? this.resizeWindowToFit() : window.close();
            },
            onChildNavigate: function(e)
            {
                var t = !0;
                P.changeWindowLocation(e.data.url, t),
                window.close();
            },
            resizeWindowToFit: function()
            {
                var e = this.$el.outerHeight(!0),
                    t = 75,
                    n = window.outerHeight;
                n && (t = n - $(window).height());
                var i = e + t,
                    o = this.$el.outerWidth(!0),
                    s = o + P.scrollbarWidth() + 20;
                window.resizeTo(s, i);
            }
        });
    }),
P.Module.define("PinCloseupSettings", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("PinCloseupShare", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("PinComment", [],
    function()
    {
        return P.Module.extend({
            initialize: function()
            {
                this.childListen("commentDeleteSuccess", this.onPinCommentDelete);
            },
            onPinCommentDelete: function()
            {
                var e = this;
                this.$el.slideUp(300,
                    function()
                    {
                        e.destroy();
                    });
            }
        });
    }),
P.Module.define("PinCommentList", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .showAll": "onShowAll",
                "focus .content": "onFocusCommentInput",
                "click .addComment": "addComment",
                "mousedown .content": "onTextAreaMouseDown",
                "keydown .content": "onTextAreaPossiblyResized",
                "mouseup .content": "onTextAreaPossiblyResized"
            },
            initialize: function()
            {
                this.commentContentHeight = null;
            },
            addComment: function()
            {
                P.trackGAEvent("comment_create", P.CONST.GA_ACTION_CLICK_SUBMIT);
                var e = this.getChildById("pinCommentField").getValue(),
                    t = this.options.pin_id,
                    n = new P.Resource("PinCommentResource", {
                        pin_id: t,
                        text: e
                    }),
                    i = this.getChildById("addCommentButton");
                i.showLoading(),
                n.call("create", {
                    success: function()
                    {
                        P.trackGAEvent("comment_create", P.CONST.GA_ACTION_SUCCESS),
                        P.pubsub.publish(t, P.CONST.PUBSUB_TOPIC_PIN_COMMENT_CREATED);
                    },
                    complete: function()
                    {
                        i.hideLoading();
                    }
                });
            },
            onContentReady: function()
            {
                var e = this.options.pin_id;
                if (e)
                {
                    var t = {};
                    t[P.CONST.PUBSUB_TOPIC_PIN_COMMENT_CREATED] = this.onPinCommentCreated,
                    this.pubsubSubscribe(e, t);
                }
            },
            onPinCommentCreated: function()
            {
                this.options.count++,
                this.render();
            },
            onShowAll: function(e)
            {
                e.stopPropagation(),
                e.preventDefault();
                var t = this.options.count;
                this.options.max_num_to_show = t,
                this.render();
            },
            onFocusCommentInput: function()
            {
                var e = this.$el.find(".addComment");
                this.options.type && "closeup" === this.options.type ? e.css("display", "block") : e.show(),
                this.triggerEvent(P.CONST.EVENT_DIMS_CHANGED, null, !0);
            },
            onTextAreaMouseDown: function()
            {
                this.commentContentHeight = this.$(".content").height();
            },
            onTextAreaPossiblyResized: function()
            {
                if (null !== this.commentContentHeight)
                {
                    var e = this.$(".content").height();
                    this.commentContentHeight !== e && (this.triggerEvent(P.CONST.EVENT_DIMS_CHANGED, null, !0), this.commentContentHeight = e);
                }
            }
        });
    }),
P.Module.define("PinCreate", [],
    function()
    {
        var e = P.Module.extend({
            initialize: function()
            {
                _.bindAll(this, "onPinCreateSuccess");
            },
            onButtonClick: function(e)
            {
                var t = e.target;
                switch (t.id)
                {
                    case "submitButton":
                        P.trackGAEvent(this.GACategory, P.CONST.GA_ACTION_CLICK_SUBMIT);
                        break;
                    case "cancelButton":
                        P.trackGAEvent(this.GACategory, P.CONST.GA_ACTION_CLICK_CANCEL),
                        this.modal || this.destroy();
                }
            },
            onContentReady: function()
            {
                this.GACategory = this.isRepin() ? "repin_create" : "pin_create",
                this.pinForm = this.getChildById("pinForm"),
                this.listen(this.pinForm, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick),
                this.boardPicker = this.pinForm.getChildById("boardPicker");
                var e = this.pinForm.form;
                this.listen(this.boardPicker, P.CONST.EVENT_BOARD_SELECTED, _.bind(e.enableSubmitButtons, e)),
                this.boardPicker.getSelectedBoardId() || e.disableSubmitButtons();
            },
            onSubmitValidated: function(e)
            {
                var t = e.data;
                t.errors[0] || this.createPin();
            },
            isRepin: function()
            {
                return !(!this.data || !this.data.id);
            },
            getPinResource: function()
            {
                var e = "PinResource",
                    t = _.extend(this.pinForm.getData(), _.pick(this.options, "method", "is_video"));
                return this.isRepin() && (e = "RepinResource", t.pin_id = this.data.id),
                new P.Resource(e, t);
            },
            createPin: function()
            {
                this.showLoading(!0);
                var e = this,
                    t = this.getPinResource();
                t.call("create", {
                    success: P.stopwatch.wrapContinuation("PinCreate.createPin success", this.onPinCreateSuccess),
                    error: P.stopwatch.wrapContinuation("PinCreate.createPin error",
                        function(t)
                        {
                            if (P.trackGAEvent(this.GACategory, P.CONST.GA_ACTION_ERROR), "create" === e.options.action && 401 === t.http_status)
                            {
                                var n = {
                                    name: "ConfirmDialog",
                                    options: {
                                        fluid: !0,
                                        template: "blocked_source"
                                    }
                                };
                                P.loadModule(n,
                                    function(t)
                                    {
                                        t.render(function()
                                        {
                                            e.parent.appendChild(t),
                                            e.destroy();
                                        });
                                    });
                            }
                            else
                            {
                                P.showError(t.message);
                            }
                        }),
                    complete: P.stopwatch.wrapContinuation("PinCreate.createPin complete",
                        function()
                        {
                            e.hideLoading();
                        })
                });
            },
            onPinCreateSuccess: function(e)
            {
                P.trackGAEvent(this.GACategory, P.CONST.GA_ACTION_SUCCESS);
                var t = this,
                    n = e.resource_response.data,
                    i = n.board,
                    o = i.url,
                    s = this.options.action,
                    r = i.name,
                    a = i.privacy,
                    l = i.is_collaborative,
                    u = {
                        id: "pinSuccess",
                        name: "PinCreateSuccess",
                        options: {
                            action: s,
                            board: r,
                            board_url: o,
                            pin_id: n.id,
                            is_collaborative: l,
                            privacy: a
                        },
                        resource: P.Resource.NOOP_RESOURCE
                    };
                this.showLoading(),
                P.loadModule(u, P.stopwatch.wrapContinuation("onPinCreateSuccess",
                    function(e)
                    {
                        var n = t.modal;
                        n ? n.setModule(e) : e.render(function()
                        {
                            t.parent.appendChild(e),
                            t.destroy();
                        });
                    })),
                this.triggerEvent(P.CONST.EVENT_PIN_CREATE, n),
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_PIN_CREATED, n),
                P.pubsub.publish(n.board.id, P.CONST.PUBSUB_TOPIC_PIN_CREATED, n);
            },
            loadFromData: function(e, t)
            {
                var n = this.getChildById("pinForm");
                e.id && (this.data = {
                        id: e.id
                    },
                n.loadAndInsertPinDupWarning(e.id)),
                e.description && this.$('[name="description"]').val(e.description);
                var i = e.images["236x"];
                if (i || e.is_video)
                {
                    var o = n.getChildById("pinPreview");
                    i && (o.options.image_url = i.url),
                    o.options.is_video = e.is_video || !1,
                    o.render();
                }
                var s = n.getChildById("boardPicker");
                s.loading = !0,
                s.render(t || void 0);
            }
        });
        return P.stopwatch.wrapMethods(e.prototype, "PinCreate", ["createPin", "onPinCreateSuccess"]),
        e;
    }),
P.Module.define("PinCreateSuccess", [],
    function()
    {
        var e = 2e3,
            t = 1e4,
            n = 1e3;
        return P.Module.extend({
            onContentReady: function()
            {
                var n = e,
                    i = !1,
                    o = this.getChildById("successBoard");
                if (o && o.hasBoard())
                {
                    n = t,
                    i = !0;
                    var s = {};
                    s[P.CONST.PUBSUB_TOPIC_USER_FOLLOW] = this.onBoardFollow,
                    this.pubsubSubscribe(o.getBoardId(), s);
                }
                i || this.$el.addClass("noBody"),
                this.closeOnDelay(n);
            },
            closeOnDelay: function(e)
            {
                this.closeTimer && clearTimeout(this.closeTimer);
                var t = this;
                this.closeTimer = setTimeout(function()
                {
                    t.closeTimer = null,
                    t.destroy();
                },
                    e);
            },
            onBoardFollow: function()
            {
                this.closeOnDelay(n);
            }
        });
    }),
P.Module.define("PinCreateSuccessBoard", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.hasBoard || this.hide();
            },
            hasBoard: function()
            {
                return !!this.getChildById("board");
            },
            getBoardId: function()
            {
                return this.extraData.boardId;
            }
        });
    }),
P.Module.define("PinDeleteCommentButton", ["InlineHoverButton"],
    function(e)
    {
        return e.extend({
            events: {
                click: "onClick"
            },
            showConfirmation: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "delete_comment"
                        }
                    };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM, e.onDeleteConfirm);
                    });
            },
            onDeleteConfirm: function()
            {
                P.trackGAEvent("comment_delete", P.CONST.GA_ACTION_CLICK_SUBMIT);
                var e = {
                    pin_id: this.options.pin_id,
                    comment_id: this.options.comment_id
                },
                    t = new P.Resource("PinCommentResource", e),
                    n = this;
                t.call("delete", {
                    success: function()
                    {
                        P.trackGAEvent("comment_delete", P.CONST.GA_ACTION_SUCCESS),
                        n.triggerEvent("commentDeleteSuccess", this, !0);
                    },
                    error: function()
                    {
                        P.trackGAEvent("comment_delete", P.CONST.GA_ACTION_ERROR);
                    }
                });
            },
            onClick: function()
            {
                P.trackGAEvent("comment_delete", P.CONST.GA_ACTION_OPEN_MODAL),
                this.showConfirmation();
            }
        });
    }),
P.Module.define("PinDupWarning", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("PinEdit", [],
    function()
    {
        var e = "pin_delete",
            t = "pin_edit";
        return P.Module.extend({
            onContentReady: function()
            {
                this.pinForm = this.getChildById("pinForm"),
                this.boardPicker = this.pinForm.getBoardPicker(),
                this.listen(this.pinForm, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onButtonClick: function(n)
            {
                var i = n.target;
                switch (i.id)
                {
                    case "submitButton":
                        P.trackGAEvent(t, P.CONST.GA_ACTION_CLICK_SUBMIT);
                        break;
                    case "cancelButton":
                        P.trackGAEvent(t, P.CONST.GA_ACTION_CLICK_CANCEL);
                        break;
                    case "deleteButton":
                        P.trackGAEvent(e, P.CONST.GA_ACTION_OPEN_MODAL),
                        this.showConfirmation();
                }
            },
            onDeleteConfirm: function()
            {
                P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK_SUBMIT),
                this.deletePin();
            },
            onSubmitValidated: function(e)
            {
                var t = e.data;
                t.errors[0] || (this.needConfirm() ? this.showPrivacyChangeConfirmation() : this.savePin());
            },
            showConfirmation: function()
            {
                var t = this,
                    n = {
                        name: "ConfirmDialog",
                        options: {
                            template: "delete_pin",
                            ga_category: e
                        }
                    };
                P.loadModule(n,
                    function(e)
                    {
                        t.showInModal(e),
                        t.listen(e, P.CONST.EVENT_CONFIRM, t.onDeleteConfirm);
                    });
            },
            showPrivacyChangeConfirmation: function()
            {
                var e = this,
                    n = {
                        name: "ConfirmDialog",
                        options: {
                            template: "change_pin_privacy"
                        }
                    };
                P.loadModule(n,
                    function(n)
                    {
                        e.showInModal(n),
                        e.listen(n, P.CONST.EVENT_CONFIRM,
                            function()
                            {
                                P.trackGAEvent(t, P.CONST.GA_ACTION_CLICK_CONFIRM),
                                e.savePin();
                            });
                    });
            },
            needConfirm: function()
            {
                var e = this.boardPicker.getPrivacy();
                return "secret" === this.data.board.privacy && "public" === e;
            },
            savePin: function()
            {
                var e = this,
                    n = this.data.id,
                    i = this.pinForm.getData();
                i.id = n;
                var o = new P.Resource("PinResource", i),
                    s = function(e)
                    {
                        P.trackGAEvent(t, P.CONST.GA_ACTION_ERROR),
                        P.showError(e.message);
                    },
                    r = function(i)
                    {
                        if (P.trackGAEvent(t, P.CONST.GA_ACTION_SUCCESS), i)
                        {
                            var o = i.resource_response;
                            if (o && !o.error)
                            {
                                if (e.isInModal())
                                {
                                    P.pubsub.publish(n, P.CONST.PUBSUB_TOPIC_PIN_UPDATED, o.data),
                                    e.destroy();
                                }
                                else
                                {
                                    var r = "/pin/" + n + "/";
                                    e.navigate(r);
                                }
                                return;
                            }
                        }
                        s();
                    };
                this.showLoading(!0),
                o.call("update", {
                    success: r,
                    error: s,
                    complete: function()
                    {
                        e.hideLoading();
                    }
                });
            },
            deletePin: function()
            {
                var t = this.data.id,
                    n = this,
                    i = {
                        id: t
                    },
                    o = new P.Resource("PinResource", i),
                    s = function(t)
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_ERROR),
                        P.showError(t.message);
                    },
                    r = function(i)
                    {
                        if (P.trackGAEvent(e, P.CONST.GA_ACTION_SUCCESS), i)
                        {
                            var o = i.resource_response;
                            if (o && !o.error)
                            {
                                if (n.isInModal())
                                {
                                    P.pubsub.publish(t, P.CONST.PUBSUB_TOPIC_PIN_DELETED),
                                    n.destroy();
                                }
                                else
                                {
                                    var r = n.data.board.url;
                                    n.navigate(r);
                                }
                                return;
                            }
                        }
                        s(i);
                    };
                this.showLoading(!0),
                o.call("delete", {
                    success: r,
                    error: s,
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("PinEmail", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {
                    pin: [P.Validator.Required()],
                    email: [P.Validator.Required(), P.Validator.Email()],
                    recipient_name: [P.Validator.Required()]
                };
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form"), e),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onButtonClick: function(e)
            {
                var t = e.target;
                t && ("submitButton" === t.id ? P.trackGAEvent("pin_email", P.CONST.GA_ACTION_CLICK_SUBMIT) : "cancelButton" === t.id && P.trackGAEvent("pin_email", P.CONST.GA_ACTION_CLICK_CANCEL));
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.sendEmail();
            },
            sendEmail: function()
            {
                var e = this.$("form").serializeArray(),
                    t = {},
                    n = this.getChildById("submitButton"),
                    i = this;
                _.each(e,
                    function(e)
                    {
                        t[e.name] = e.value;
                    }),
                n.showLoading();
                var o = {
                    name: "ConfirmDialog",
                    options: {
                        template: "email_pin",
                        recipient_name: t.recipient_name
                    }
                },
                    s = new P.Resource("EmailPinResource", t);
                s.call("create", {
                    success: function()
                    {
                        P.trackGAEvent("pin_email", P.CONST.GA_ACTION_SUCCESS),
                        P.loadModule(o,
                            function(e)
                            {
                                i.showInModal(e),
                                i.listen(e, P.CONST.EVENT_CONFIRM, i.destroy);
                            });
                    },
                    error: function(e)
                    {
                        P.trackGAEvent("pin_email", P.CONST.GA_ACTION_ERROR),
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("PinFlagCommentButton", ["InlineHoverButton"],
    function(e)
    {
        return e.extend({
            events: {
                click: "onClick"
            },
            showReasonModal: function()
            {
                var e = this,
                    t = {
                        name: "FlagComment",
                        options: {
                            pin_id: this.options.pin_id,
                            comment_id: this.options.comment_id
                        }
                    };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t);
                    });
            },
            onClick: function()
            {
                P.trackGAEvent("comment_flag", P.CONST.GA_ACTION_OPEN_MODAL),
                this.showReasonModal();
            }
        });
    }),
P.Module.define("PinForm", ["UserSocialNetworkSettings"],
    function(e)
    {
        var t = P.SocialConnect.FACEBOOK,
            n = P.SocialConnect.TWITTER,
            i = "secret",
            o = ".socialShareWrapper";
        return e.extend({
            events: {
                'change [name="share_facebook"]': "onFacebookCheckboxChanged"
            },
            initialize: function()
            {
                this.networkToSelectorMap = {},
                this.networkToSelectorMap[t] = '[name="share_facebook"]',
                this.networkToSelectorMap[n] = '[name="share_twitter"]';
            },
            onFacebookCheckboxChanged: function()
            {
                var t = this.getNetworkChecked(P.SocialConnect.FACEBOOK);
                t && e.prototype.maybeRequestFbTimelinePermission.call(this, {
                    error: function()
                    {
                        this.setNetworkChecked(P.SocialConnect.FACEBOOK, !t);
                    }
                });
            },
            onContentReady: function()
            {
                var e = {
                    description: [P.Validator.Required(), P.Validator.Length({
                        max: P.CONST.MAX_CHARS_FOR_BOARD_PIN_DESCRIPTION
                    })]
                };
                this.form = new P.Form(this.$("form"), e),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                "FR" === P.currentUser.get("country") && this.form.enableFastValidateOnField("description"),
                this.childListen(P.CONST.EVENT_BOARD_SELECTED, this.onBoardSelected),
                this._boardPicker = this.getBoardPicker(),
                this._boardPicker.getPrivacy() === i && this.hideSocialExplicitSharing(),
                this.extraData.facebookTimelineEnabled && P.e.epfftensp && "done" !== Cookie.get("first_time_timeline_exp") && (Cookie.set("first_time_timeline_exp", "pre-checked"), this.setNetworkChecked(P.SocialConnect.FACEBOOK, !0));
                var t = this.getChildById("uploader");
                t && this.listen(t, P.CONST.EVENT_UPLOAD_SUCCESS, this.onUploadSuccess);
            },
            onBoardSelected: function(e)
            {
                e.data.privacy === i ? this.hideSocialExplicitSharing() : this.showSocialExplicitSharing();
            },
            hideSocialExplicitSharing: function()
            {
                this.$(o).hide();
            },
            showSocialExplicitSharing: function()
            {
                this.$(o).show();
            },
            onSubmitValidated: function(e)
            {
                this.triggerEvent(P.CONST.EVENT_SUBMIT_VALIDATED, e, !0);
            },
            onUploadSuccess: function(e)
            {
                var t = e.data.image_url,
                    n = this.getChildById("pinPreview");
                n.setImage(t),
                this.options.image_url = t;
            },
            getBoardPicker: function()
            {
                return this.getChildById("boardPicker");
            },
            getBoardId: function()
            {
                return this._boardPicker.getSelectedBoardId();
            },
            getDescription: function()
            {
                return this.getChildById("pinDescriptionField").getValue();
            },
            setNetworkChecked: function(e, t)
            {
                var n = this.networkToSelectorMap[e];
                n && this.$(n).attr("checked", t);
            },
            getNetworkChecked: function(e)
            {
                var t = this.networkToSelectorMap[e];
                if (t)
                {
                    var n = this.$(t);
                    return n.length ? n.is(":checked") : "";
                }
            },
            getImageUrl: function()
            {
                return this.options.image_url;
            },
            getLink: function()
            {
                return this.$("#pinFormLink").val();
            },
            getData: function()
            {
                this.extraData.facebookTimelineEnabled && P.e.epfftensp && "pre-checked" === Cookie.get("first_time_timeline_exp") && Cookie.set("first_time_timeline_exp", "done");
                var e = {
                    board_id: this.getBoardId(),
                    description: this.getDescription(),
                    link: this.getLink()
                },
                    t = this.getNetworkChecked(P.SocialConnect.TWITTER);
                "" !== t && (e.share_twitter = t),
                t = this.getNetworkChecked(P.SocialConnect.FACEBOOK),
                "" !== t && (e.share_facebook = t);
                var n = this.getImageUrl();
                return n && (e.image_url = n),
                e;
            },
            loadAndInsertPinDupWarning: function(e)
            {
                var t = {
                    name: "PinDupWarning",
                    resource: {
                        name: "PinResource",
                        options: {
                            id: e,
                            field_set_key: "faster_repin"
                        }
                    }
                },
                    n = this;
                P.loadModule(t,
                    function(e)
                    {
                        e.render(function()
                        {
                            e.getElement().insertAfter(n.$(".pinFormHeader"));
                        });
                    });
            }
        });
    }),
P.Module.define("PinLikeButton", ["Button"],
    function(e)
    {
        var t = "unlike";
        return e.extend({
            onClick: function()
            {
                this.ensureAuthentication() && this.toggle();
            },
            setState: function(e)
            {
                var n = this.$el;
                this.options.liked = e,
                e ? (n.addClass(t), this.$(".buttonText").html(n.data("text-unlike"))) : (n.removeClass(t), this.$(".buttonText").html(n.data("text-like")));
            },
            getPinLikeResource: function()
            {
                return new P.Resource("PinLikeResource", {
                    pin_id: this.options.pin_id
                });
            },
            toggle: function()
            {
                var e, t, n;
                this.options.liked ? (e = "pin_unlike", t = "delete", n = P.CONST.PUBSUB_TOPIC_PIN_UNLIKED) : (e = "pin_like", t = "create", n = P.CONST.PUBSUB_TOPIC_PIN_LIKED),
                P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK);
                var i = this,
                    o = this.getPinLikeResource();
                this.showLoading(),
                o.call(t, {
                    success: function()
                    {
                        P.trackGAEvent(e, P.CONST.GA_ACTION_SUCCESS),
                        i.setState(!i.options.liked),
                        P.pubsub.publish(i.options.pin_id, n);
                    },
                    complete: function()
                    {
                        i.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("PinSend", ["ui.TypeaheadField", "UserSocialNetworkSettings"],
    function(e, t)
    {
        var n = "active",
            i = "animate",
            o = "hidden",
            s = 2600;
        return t.extend({
            events: {
                "click .undoSendPin": "hideFakeSuccess"
            },
            onAddedToDom: function()
            {
                this._messageShowing = !1,
                this._hasQueriedTypeahead = !1;
            },
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_SEARCH_QUERY_UPDATED] = this.onSearchQueryUpdated,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_SITE, e),
                this.$staticResults = this.$(".staticResults"),
                this.$message = this.$('input[name="message"]'),
                this.$beforeSend = this.$(".pinSendBeforeSend"),
                this.$afterSend = this.$(".pinSendAfterSend"),
                this.$pinSendMessageWrapper = this.$(".pinSendMessageWrapper"),
                this.$emailButtonWrapper = this.$(".emailButtonWrapper"),
                this.$facebookButtonWrapper = this.$(".facebookButtonWrapper"),
                this.$findFriend = this.$('input[name="sendPinFriendSearch"]'),
                this.typeaheadField = this.getChildById("sendPinField"),
                this.listen(this.parent, P.CONST.EVENT_DROPDOWN_SHOW, this.onEventDropdownShow),
                this.listen(this.parent, P.CONST.EVENT_DROPDOWN_HIDE, this.onHide),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick),
                this.childListen(P.CONST.EVENT_ITEM_SELECTED, this.onChildItemSelected),
                this.childListen(P.CONST.EVENT_USER_CLICK, this.onUserClick),
                this.childListen(P.CONST.EVENT_TYPEAHEAD_RESULTS_RETURNED, this.onTypeaheadResultsReturned),
                this.childListen(P.CONST.EVENT_TYPEAHEAD_NO_RESULTS_RETURNED, this.onNoTypeaheadResultsReturned),
                this.$message.placeholder(),
                this.$findFriend.placeholder();
            },
            onEventDropdownShow: function()
            {
                this.focusFriendTypeahead();
            },
            onNoTypeaheadResultsReturned: function()
            {
                this.showStaticResults(),
                this.showSendEmailButton(),
                this.focusFriendTypeahead();
            },
            onTypeaheadResultsReturned: function(e)
            {
                var t = e.data.count;
                this._hasQueriedTypeahead = !0,
                t ? (this.showStaticResults(), this.showStaticSocialOptions()) : this.showStaticSocialOptions();
            },
            hideFacebookConnectButton: function()
            {
                this.$facebookButtonWrapper.addClass(o);
            },
            showFacebookConnectButton: function()
            {
                this.$facebookButtonWrapper.removeClass(o);
            },
            hideSendEmailButton: function()
            {
                this.$emailButtonWrapper.addClass(o);
            },
            showSendEmailButton: function()
            {
                this.$emailButtonWrapper.removeClass(o);
            },
            hideStaticSocialOptions: function()
            {
                this.hideSendEmailButton(),
                this.hideFacebookConnectButton();
            },
            showStaticSocialOptions: function()
            {
                this.showSendEmailButton(),
                this.showFacebookConnectButton();
            },
            hideStaticResults: function()
            {
                this.$staticResults.addClass(o);
            },
            showStaticResults: function()
            {
                this.$staticResults.removeClass(o);
            },
            focusAddMessageField: function()
            {
                this.$message.focus();
            },
            focusFriendTypeahead: function()
            {
                this.$findFriend.focus();
            },
            onHide: function()
            {
                var e = this;
                this._timeout && this.user && (this.sendPin(), clearTimeout(e._timeout)),
                this.reset();
            },
            hideSendMessage: function()
            {
                this.$pinSendMessageWrapper.addClass(i);
            },
            showSendMessage: function()
            {
                this.$pinSendMessageWrapper.removeClass(i);
            },
            onShowMessageClick: function(e)
            {
                return this.showSendMessage(),
                e.target.$el.addClass(o),
                this.focusAddMessageField(),
                !1;
            },
            removeMessageContent: function()
            {
                this.$message.val("");
            },
            onUserClick: function(e)
            {
                var t = e.target.data,
                    n = e.target;
                t && (this.user = t, t.image_medium_url || (this.user.image_medium_url = n.getProfileImage()), this.showSuccess());
            },
            onButtonClick: function(e)
            {
                var t = this,
                    n = e.target;
                if (n)
                {
                    var i = n.id;
                    if ("addMessage" === i)
                    {
                        return this.onShowMessageClick(e),
                        void 0;
                    }
                    switch (i)
                    {
                        case "connectGmail":
                            break;
                        case "connectYahoo":
                            break;
                        case "sendEmail":
                            this.showEmailModal();
                            break;
                        case "connectFacebook":
                            this.handleConnect(P.SocialConnect.FACEBOOK, !0, {
                                complete: function()
                                {
                                    t.show();
                                },
                                success: function()
                                {
                                    t.hideFacebookConnectButton(),
                                    t.focusFriendTypeahead();
                                },
                                error: function()
                                {
                                    P.showError(P.string("connectError"));
                                }
                            });
                    }
                }
            },
            showSuccess: function()
            {
                var e = this,
                    t = this.user,
                    o = t.full_name || t.first_name,
                    r = t.image_medium_url || t.send_pin_image;
                this.$beforeSend.addClass(i),
                P.supportCSSTransitions() ? setTimeout(function()
                {
                    e.$afterSend.addClass(n);
                },
                    400) : this.$afterSend.addClass(n),
                this.$(".receiverName").text(o),
                this.$(".pinSendSuccessMug").attr("src", r),
                this._timeout = setTimeout(function()
                {
                    e.triggerEvent(P.CONST.EVENT_DROPDOWN_HIDE, null, !0);
                },
                    s);
            },
            reset: function()
            {
                this.hideFakeSuccess(),
                this.hideSendMessage(),
                this.setMessageValue(""),
                this.typeaheadField.clear(),
                this.typeaheadField.closeTypeahead(),
                this.getChildById("addMessage").$el.removeClass(o);
            },
            hideFakeSuccess: function()
            {
                var e = this;
                this.$beforeSend.removeClass(o + " " + i),
                this.$afterSend.removeClass(n + " " + i),
                clearTimeout(e._timeout),
                this._timeout = null;
            },
            getMessageValue: function()
            {
                return $.trim(this.$(".message").val());
            },
            setMessageValue: function(e)
            {
                return $.trim(this.$(".message").val(e));
            },
            sendPin: function()
            {
                var e = this,
                    t = this.options.pin_id,
                    n = this.user;
                if (n)
                {
                    var i = n.email,
                        o = n.id,
                        s = n.full_name;
                    s || (s = "");
                    var r = {
                        pin: t,
                        recipient_name: s
                    },
                        a = this.getMessageValue();
                    a && (r.message = a);
                    var l;
                    i ? (r.email = i, l = new P.Resource("EmailPinResource", r)) : (r.user_id = o, l = new P.Resource("SharePinResource", r)),
                    clearTimeout(this._timeout),
                    l.call("create", {
                        success: function()
                        {
                            e.user = null;
                        },
                        error: function()
                        {
                            P.showError(P.string("errorMessage"));
                        }
                    }),
                    this.user = null;
                }
            },
            showTypeaheadResults: function()
            {
                var e = this.getChildByModuleName("ui.Typeahead");
                e.show();
            },
            showEmailModal: function(e)
            {
                var t = this,
                    n = {
                        name: "PinEmail",
                        options: {
                            pin_id: this.options.pin_id,
                            pin_image: this.options.pin_image
                        }
                    };
                e && (n.options.name = e.name);
                var i = this.getMessageValue();
                i && (n.options.message = i),
                P.loadModule(n,
                    function(e)
                    {
                        t.showInModal(e);
                    });
            },
            onChildItemSelected: function(e)
            {
                e.stopPropagation();
                var t = e.data.item.attributes;
                return "user" !== t.type ? this.showEmailModal(t) : (this.user = t, this.showSuccess(), !1);
            },
            onSearchQueryUpdated: function(e, t, n)
            {
                var i = n || "";
                this.typeaheadField.setValue(i);
            }
        });
    }),
P.Module.define("PinShareButton", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("PinUploader", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.getChildById("uploader");
                this.listen(e, P.CONST.EVENT_UPLOAD_SUCCESS, this.onUploadSuccess),
                this.listen(e, P.CONST.EVENT_UPLOAD_ERROR, this.onUploadError);
            },
            onUploadSuccess: function(e)
            {
                P.trackGAEvent("pin_upload", P.CONST.GA_ACTION_SUCCESS),
                this.imageUrl = e.data.image_url,
                this.ensurePinCreate();
            },
            onUploadError: function(e)
            {
                P.trackGAEvent("pin_upload", P.CONST.GA_ACTION_ERROR),
                P.showError(P.string(e.data));
            },
            ensurePinCreate: function()
            {
                var e = this,
                    t = {
                        image_url: this.imageUrl,
                        action: "upload",
                        method: "uploaded"
                    };
                this.options.default_board_id && (t.default_board_id = this.options.default_board_id);
                var n = {
                    name: "PinCreate",
                    options: t,
                    id: "pinCreate"
                };
                this.showLoading(),
                P.loadModule(n,
                    function(t)
                    {
                        e.hideLoading(),
                        e.showInModal(t),
                        e.triggerEvent(P.CONST.EVENT_PIN_CREATE_OPENED, null, !0),
                        e.destroy();
                    });
            }
        });
    }),
P.Module.define("Pinnable", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click a.pinImageWrapper": "onClick"
            },
            initialize: function()
            {
                _.bindAll(this, "onImageLoad", "onImageError");
            },
            onAdded: function()
            {
                this.updateImage();
            },
            onClick: function()
            {
                return this.createPin(),
                !1;
            },
            createPin: function()
            {
                var e = {
                    image_url: this.options.url,
                    action: "create",
                    method: "scraped",
                    link: this.options.link
                },
                    t = {
                        name: "PinCreate",
                        options: e,
                        id: "pinCreate"
                    },
                    n = this;
                P.loadModule(t,
                    function(e)
                    {
                        n.showInModal(e);
                    });
            },
            updateImage: function()
            {
                var e = this.$(".pinImageWrapper"),
                    t = this.$img = $("<img>");
                t.on("load", this.onImageLoad),
                t.on("error", this.onImageError),
                t.attr("src", this.options.url),
                e.append(t);
            },
            onImageLoad: function()
            {
                return this.$img.width() < P.CONST.MIN_PINNABLE_IMAGE_WIDTH || this.$img.height() < P.CONST.MIN_PINNABLE_IMAGE_HEIGHT ? (P.log("Too small!", this.$img.width(), this.$img.height()), this.destroy(), void 0) : (this.$el.css("visibility", "visible"), this.$img.addClass("pinnableImage"), this.triggerEvent("contentChanged", null, !0), void 0);
            },
            onImageError: function()
            {
                this.destroy();
            }
        });
    }),
P.Module.define("PositionModule", [],
    function()
    {
        var e = "positionModuleCaret",
            t = 100,
            n = 5,
            i = P.CONST.PositionPoint,
            o = P.CONST.PositionPointFlag,
            s = {};
        return s[o.FLAG_HORIZONTAL_LEFT] = "positionLeft",
        s[o.FLAG_HORIZONTAL_RIGHT] = "positionRight",
        s[o.FLAG_VERTICAL_TOP] = "positionTop",
        s[o.FLAG_VERTICAL_BOTTOM] = "positionBottom",
        P.Module.extend({
            positionMode: P.CONST.PositionMode.ANCHORED,
            initialize: function()
            {
                var e = _.bind(this.positionModule, this);
                this.childListen(P.CONST.EVENT_CONTENT_CHANGED, e),
                this.listen(this, P.CONST.EVENT_DIMS_CHANGED, e),
                this.listen(this, P.CONST.EVENT_NAVIGATE, e),
                this.listen(P.Viewport, P.CONST.EVENT_RESIZE, e),
                this.listen(P.Viewport, P.CONST.EVENT_BODY_COLUMN_CHANGE, e);
            },
            getPositionMode: function()
            {
                return P.CONST.PositionMode[this.options.positionMode] || this.positionMode;
            },
            onOptionsChanged: function()
            {
                this.updateFixed();
            },
            getPositionElement: function()
            {
                return this.$el;
            },
            getPositionAnchor: function()
            {
                return this.options.anchor;
            },
            getPositionPoint: function()
            {
                return i[this.options.position_point] || i.BOTTOM_LEFT;
            },
            getPositionFixed: function()
            {
                return !!this.options.fixed;
            },
            getPositionCaret: function()
            {
                return this.getCaret();
            },
            getCaret: function()
            {
                return this.$("." + e);
            },
            _getPositionType: function()
            {
                return this.getPositionFixed ? "fixed" : "absolute";
            },
            positionModuleAtAnchor: function(e, t)
            {
                var n = this.getPositionElement();
                n.addClass("positionModuleElement"),
                n.toggleClass("positionFixed", this.getPositionFixed),
                _.each(s,
                    function(e)
                    {
                        n.removeClass(e);
                    }),
                t = P.Positioning.positionElementAtAnchor(n, e, t, this.getPositionFixed(), this.options.force_in_viewport);
                var i = _.find(s,
                    function(e, n)
                    {
                        return t & n ? !0 : void 0;
                    });
                n.addClass(i),
                this.positionCaret(e, t);
            },
            positionCaret: function(t, i)
            {
                var o = this.$("." + e);
                if (o.length)
                {
                    var s = P.CONST.PositionPointFlag,
                        r = this.getPositionElement();
                    r.addClass("bigCaret", !!this.options.largeCaret),
                    r.addClass("defaultCaret", !this.options.largeCaret);
                    var a = "left",
                        l = "outerWidth",
                        u = "width";
                    i & s.FLAG_HORIZONTAL && (a = "top", l = "outerHeight", u = "height");
                    var c = 0,
                        d = i & (s.FLAG_HORIZONTAL_CENTER | s.FLAG_VERTICAL_CENTER),
                        h = o[u]() > t[u]() - n;
                    h && !d && (c = (o[u]() - t[u]()) / 2 + n, (i & s.FLAG_VERTICAL_RIGHT || i & s.FLAG_HORIZONTAL_BOTTOM) && (c = -c));
                    var p = r.offset()[a],
                        f = p + r[l](),
                        m = t.offset()[a],
                        g = m + t[l](),
                        v = p;
                    v < m && (v = m);
                    var _ = f;
                    _ > g && (_ = g);
                    var C = (v + _) / 2 - o[l]() / 2 + c,
                        y = {};
                    if (y[a] = C, o.offset(y), c)
                    {
                        var T = parseInt(r.css(a), 10);
                        r.css(a, T - c);
                    }
                }
            },
            positionModule: function()
            {
                this.cleanPositionModuleElement(),
                this.getPositionMode() === P.CONST.PositionMode.ANCHORED ? this.positionModuleAtAnchor(this.getPositionAnchor(), this.getPositionPoint()) : this._positionAbsoluteCenter();
            },
            _positionAbsoluteCenter: function()
            {
                var e = this.getScrollableElement().outerHeight(),
                    n = this.getContent().outerHeight(),
                    i = (e - n) / 2;
                this.getPositionElement().css({
                    marginTop: Math.max(t, i)
                }),
                this.getContent().css({
                    width: this.getModule().getWidth(!0)
                });
            },
            cleanPositionModuleElement: function()
            {
                var e = this.getPositionElement();
                e.removeClass("positionModuleElement"),
                e.css({
                    top: "",
                    left: "",
                    margin: ""
                });
            },
            updateFixed: function()
            {
                this.$el.toggleClass("positionModuleFixed", this.getPositionFixed());
            },
            renderContainer: function()
            {
                this.empty();
                var t = this.$el;
                if (t.addClass("PositionModule"), t.addClass(this.options.class_name), this.updateFixed(), this.options.view_type && t.addClass(this.options.view_type), !this.options.hide_caret)
                {
                    var n = $('<span class="' + e + '"></span>');
                    t.prepend(n);
                }
            },
            render: function(e)
            {
                var t = _.bind(function()
                {
                    this.onContentReady(),
                    this.onRendered(),
                    e && e();
                },
                    this);
                this.options.module ? P.loadModule(this.options.module, _.bind(function(e)
                {
                    this.insertChild(e, this.getPositionElement()),
                    e.render(t);
                },
                    this)) : t();
            }
        });
    }),
P.Module.define("RecFeedHomePage", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                var e = this.getChildById("grid"),
                    t = "none";
                e && !e.hasItems() && (e.remove(), t = "block"),
                this.$(".noResults").css("display", t);
            }
        });
    }),
P.Module.define("RecentContacts", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("RelatedInterests", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("RepinsLikesFeedPage", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("RichPinBase", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = this.$(".richMapCanvas"),
                    t = e.data("lat"),
                    n = e.data("lon");
                if (P.e.rpl && e && t && n)
                {
                    var i = new google.maps.LatLng(t, n),
                        o = {
                            center: i,
                            disableDoubleClickZoom: !0,
                            disableDefaultUI: !0,
                            draggable: !1,
                            mapTypeId: google.maps.MapTypeId.ROADMAP,
                            scrollwheel: !1,
                            scaleControl: !1,
                            zoom: 8
                        },
                        s = new google.maps.Map(e[0], o);
                    new google.maps.Marker({
                        clickable: !1,
                        position: i,
                        map: s
                    }),
                    setTimeout(function()
                    {
                        google.maps.event.trigger(s, "resize"),
                        s.setCenter(i);
                    },
                        10);
                }
            }
        });
    }),
P.Module.define("RichPinDebugger", [],
    function()
    {
        var e = "hidden",
            t = "selected";
        return P.Module.extend({
            events: {
                "click .menu .main": "onShowMain",
                "click .menu .scraped": "onShowScraped",
                "click .menu .parsed": "onShowParsed"
            },
            onContentReady: function()
            {
                this.$form = this.$("form"),
                this.$main = this.$(".section.main"),
                this.$menus = this.$(".menu a"),
                this.$scraped = this.$(".section.scraped"),
                this.$sections = this.$(".section"),
                this.$parsed = this.$(".section.parsed"),
                this.form = new P.Form(this.$form),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.retrieve);
            },
            retrieve: function()
            {
                var e = this,
                    t = this.$form.serializeArray(),
                    n = t[0].value,
                    i = {
                        link: n
                    },
                    o = this.getChildById("submitButton"),
                    s = new P.Resource("RichPinReindexResource", i),
                    r = function(t)
                    {
                        var i = encodeURIComponent(n);
                        if (t && !t.resource_response.error && t.resource_response.data)
                        {
                            var o = t.resource_response.data;
                            i = encodeURIComponent(o.url);
                        }
                        e.navigate("?link=" + i);
                    };
                o.showLoading(),
                s.call("create", {
                    success: r,
                    complete: function()
                    {
                        o.hideLoading();
                    }
                });
            },
            onShowMain: function(n)
            {
                return this.hideAllMenus(),
                this.$main.removeClass(e),
                $(n.target).addClass(t),
                !1;
            },
            onShowParsed: function(n)
            {
                return this.hideAllMenus(),
                this.$parsed.removeClass(e),
                $(n.target).addClass(t),
                !1;
            },
            onShowScraped: function(n)
            {
                return this.hideAllMenus(),
                this.$scraped.removeClass(e),
                $(n.target).addClass(t),
                !1;
            },
            hideAllMenus: function()
            {
                this.$sections.addClass(e),
                this.$menus.removeClass(t);
            }
        });
    }),
P.Module.define("RichPinDebuggerItem", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("RichPinHeading", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("ScrollToTop", [],
    function()
    {
        var e = "visible",
            t = 300,
            n = 500,
            i = P.Module.extend({
                events: {
                    "click button": "onScrollToTopClick"
                },
                $scroller: null,
                initialize: function()
                {
                    this.visible = !1;
                },
                setScroller: function(e)
                {
                    this.scrollListener && (this.removeListener(this.scrollListener), this.scrollListener = null),
                    this.$scroller = e,
                    this.$scroller.length > 0 && (this.updateButtonVisibility(), this.scrollListener = this.listen(this.$scroller, "scroll", this.updateButtonVisibility));
                },
                updateButtonVisibility: function()
                {
                    var e = this.$scroller.scrollTop();
                    e > n ? this.showButton() : this.hideButton();
                },
                onScrollToTopClick: function()
                {
                    var e = this,
                        n = this.$scroller;
                    n[0] === window && (n = $("body,html")),
                    n.animate({
                            scrollTop: 0
                        },
                        {
                            duration: t,
                            complete: function()
                            {
                                e.animateButtonOut();
                            }
                        }),
                    P.trackGAEvent("scroll_to_top", P.CONST.GA_ACTION_CLICK);
                },
                animateButtonIn: function()
                {
                    var t = this;
                    P.deferDomManipulation(function()
                    {
                        t.$el.addClass(e);
                    });
                },
                animateButtonOut: function()
                {
                    var t = this;
                    P.deferDomManipulation(function()
                    {
                        t.$el.removeClass(e);
                    });
                },
                showButton: function()
                {
                    this.visible || (this.visible = !0, this.animateButtonIn());
                },
                hideButton: function()
                {
                    this.visible && (this.visible = !1, this.animateButtonOut());
                }
            });
        return P.stopwatch.wrapMethods(i.prototype, "ScrollToTop", ["updateButtonVisibility"]),
        i;
    }),
P.Module.define("SearchInfoBar", ["InfoBarBase"],
    function(e)
    {
        return e.extend({
            onContentReady: P.NOOP,
            onTabClick: P.NOOP,
            setScope: function(e)
            {
                var t = this.$("." + e);
                t.length && this.selectTab(t.attr("href"));
            }
        });
    }),
P.Module.define("SearchPage", [],
    function()
    {
        var e = "new",
            t = ".noResults",
            n = "hidden";
        return P.Module.extend({
            universalSearch: !1,
            onContentReady: function()
            {
                this.universalSearch && this.showNoResultMessage();
            },
            onDestroyed: function()
            {
                this.publishSearchChange();
            },
            onRemovedFromDom: function()
            {
                this.publishSearchChange();
            },
            onAdded: function()
            {
                var e = _.pick(this.options, "query", "scope");
                this.publishSearchChange(e);
            },
            onAddedToDom: function()
            {
                this.universalSearch = this.$el.hasClass(e),
                this.universalSearch && this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate);
            },
            onChildNavigate: function(e)
            {
                if (this.universalSearch)
                {
                    var t = e.data.url;
                    if (P.isOffsiteUrl(t))
                    {
                        return;
                    }
                    var n = P.router.resolve(e.data.url);
                    if ("SearchPage" === n.module)
                    {
                        return e.data.handled = !0,
                        void 0;
                    }
                }
                return !1;
            },
            setAsMainModule: function(e, t, n, i)
            {
                var o = this.getChildById("searchSidebar"),
                    s = this.getChildById("searchContent");
                if (!s || !o)
                {
                    return this.showNoResultMessage(),
                    P.Module.prototype.setAsMainModule.apply(this, arguments);
                }
                if (this.hasSameOptions(e, t) && this.contentReady && !this._forceRefresh(n))
                {
                    return i && i(),
                    void 0;
                }
                this.setOptions(e),
                this.setResource(t);
                var r = e.scope;
                o.setScope(r);
                var a = "variable_height",
                    l = !0;
                this.showNoResultMessage(!0),
                r in ["boards", "users", "people"] && (a = "fixed_height", l = !1),
                s.options.layout = a,
                s.options.show_grid_footer = l,
                s.resource.options.scope = r,
                s.empty(),
                s.showLoading(),
                s.resource.abort(),
                s.render(_.bind(function()
                {
                    s.hideLoading(),
                    this.showNoResultMessage();
                },
                    this)),
                i && i();
            },
            showNoResultMessage: function(e)
            {
                var i = this.getChildById("searchContent");
                this.$(t).toggleClass(n, e || i && i.hasItems());
            },
            publishSearchChange: function(e)
            {
                e = e || {},
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_SEARCH_QUERY_UPDATED, e.query || ""),
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_SEARCH_SCOPE_UPDATED, e.scope || "");
            }
        });
    }),
P.Module.define("SearchScopeSelector", [],
    function()
    {
        return P.Module.extend({
            events: {
                "change input": "onScopeChange"
            },
            onAddedToDom: function()
            {
                var e = this.options.scope;
                this.$("input").each(function()
                {
                    var t = $(this);
                    t.prop("checked", t.val() === e);
                });
            },
            onScopeChange: function(e)
            {
                var t = $(e.currentTarget).val();
                if (t !== this.options.scope)
                {
                    var n = window.location.search;
                    this.navigate("/search/" + t + "/" + n);
                }
            }
        });
    }),
P.Module.define("SearchSidebar", [],
    function()
    {
        var e = "searchInfoBar",
            t = 70,
            n = "searchRelated";
        return P.Module.extend({
            sidebarRelated: null,
            infoBar: null,
            setScope: function(e)
            {
                this.options.scope !== e && (this.options.scope = e, this.infoBar.setScope(this.options.scope), this.sidebarRelated.setScope(this.options.scope));
            },
            setSticky: function()
            {
                var e = this.$(".searchSidebarInner");
                this.$el.toggleClass("sticky", P.Viewport.height > e.height() + t);
            },
            onContentReady: function()
            {
                this.infoBar = this.getChildById(e),
                this.sidebarRelated = this.getChildById(n),
                this.sidebarRelated.setScope(this.options.scope),
                this.setSticky(),
                this.listen(P.Viewport, P.CONST.EVENT_RESIZE, _.bind(this.setSticky, this));
            }
        });
    }),
P.Module.define("SearchSidebarRelated", [],
    function()
    {
        var e = ".searchSidebarSection";
        return P.Module.extend({
            setScope: function(e)
            {
                this.options.scope !== e && (this.options.scope = e, this.render());
            },
            onContentReady: function()
            {
                this.parent.setSticky(),
                _.each(this.children,
                    function(t)
                    {
                        var n = t.getElement().parents(e);
                        t.destroyIfEmpty() && $(n).remove();
                    });
            }
        });
    }),
P.Module.define("ShowModalButton", ["Button", "ModalTrigger"],
    function(e, t)
    {
        var n = _.extend({
                onClick: function(e)
                {
                    if (P.stopwatch.setNote("submoduleName", this.options.submodule.name), this.isDisabled())
                    {
                        return e.preventDefault(),
                        !1;
                    }
                    var t = this.options.require_auth,
                        n = P.currentUser.isAuthenticated();
                    if (t && !n)
                    {
                        var i = this.options.url;
                        return i || (i = P.getRegisterUrl()),
                        this.navigate(i);
                    }
                    var o = this.options.submodule;
                    if (P.e.fr && o.options && o.options.use_template_module)
                    {
                        this.disable();
                        var s = this,
                            r = {
                                moduleName: o.name,
                                data: o.options.template_module_data,
                                callback: function(e)
                                {
                                    s.showInModal(e),
                                    s.enable();
                                }
                            };
                        P.TemplateModuleLoader.instance().buildTemplateModule(r);
                    }
                    else
                    {
                        this.showModal();
                    }
                    return !1;
                },
                toString: function()
                {
                    return this.className + "(module=" + this.options.submodule.name + ")";
                }
            },
            t.prototype),
            i = e.extend(n);
        return P.stopwatch.wrapMethods(i.prototype, "ShowModalButton", ["onClick"]),
        i;
    }),
P.Module.define("SocialNetworkSettingsBase", [],
    function()
    {
        return P.Module.extend({
            events: {},
            handleConnect: function(e, t, n)
            {
                var i = this;
                if (t)
                {
                    var o = {
                        success: function(o)
                        {
                            var s = {
                                network: e,
                                data: o
                            };
                            i._internalConnectNetwork(t, s, n);
                        },
                        error: function()
                        {
                            P.showError(P.string("connectError")),
                            n.error && n.error(),
                            n.complete && n.complete();
                        }
                    };
                    this._externalConnectNetwork(e, t, o);
                }
                else
                {
                    var s = {
                        network: e
                    };
                    this._internalConnectNetwork(t, s, n);
                }
            },
            _externalConnectNetwork: function(e, t, n)
            {
                if (!t)
                {
                    return n.success && n.success(),
                    void 0;
                }
                var i = P.SocialConnect.instance();
                i.connect(e, n);
            },
            _internalConnectNetwork: function(e, t, n)
            {
                var i = e ? "create" : "delete",
                    o = new P.Resource("UserSocialNetworkResource", t);
                o.call(i, n);
            }
        });
    }),
P.Module.define("TextContainer", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("TweetButton", ["Button"],
    function(e)
    {
        return e.extend({
            onClick: function()
            {
                var e = this.options.ga_category || "share_twitter";
                P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK),
                this.openWebIntent();
            },
            openWebIntent: function()
            {
                var e = this.getWindowUrl(),
                    t = 550,
                    n = 420;
                return P.window.open(e, null, t, n);
            },
            getWindowUrl: function()
            {
                var e = "https://twitter.com/intent/tweet?via=pinterest",
                    t = {};
                return this.options.tweet_path && (t.url = encodeURIComponent(P.absolutify(this.options.tweet_path))),
                this.options.tweet_text && (t.text = encodeURIComponent(this.options.tweet_text)),
                _.reduce(t,
                    function(e, t, n)
                    {
                        return e + "&" + n + "=" + t;
                    },
                    e);
            }
        });
    }),
P.Module.define("UnauthHomePage", [],
    function()
    {
        var e = "hidden",
            t = 985,
            n = 461;
        return P.Module.extend({
            events: {},
            initialize: function()
            {
                this._minWindowHeight = 810,
                this._minImageHeight = 200;
            },
            onNavigateEvent: function(e)
            {
                var t = e.target.id,
                    n = "emailSignup",
                    i = [n];
                if (t && -1 !== $.inArray(t, i))
                {
                    var o;
                    t === n && (o = "register_email"),
                    e.target.options.url,
                    o && P.trackRegisterAction(o);
                }
            },
            onAddedToDom: function()
            {
                this.resize();
            },
            onContentReady: function()
            {
                var e = this;
                this.resize(),
                $(window).on("resize", _.bind(this.resize, this));
                var t = this.getChildById("facebookSignup");
                P.trackRegisterAction("unauth_home"),
                this.childListen(P.CONST.EVENT_NAVIGATE, this.onNavigateEvent),
                t && this.listen(t, P.CONST.EVENT_BUTTON_CLICK, this.onFacebookButtonClick),
                this.$(".homeUnauthImage").load(function()
                {
                    e.resize();
                });
            },
            onFacebookButtonClick: function()
            {
                var e = P.SocialConnect.instance(),
                    t = this;
                P.trackRegisterAction("register_facebook_attempt"),
                e.connect("facebook", {
                    success: function(e)
                    {
                        t.login({
                            facebook_id: e.id,
                            facebook_token: e.access_token
                        });
                    }
                });
            },
            login: function(e)
            {
                var t = function()
                {
                    P.navigate("/");
                },
                    n = function()
                    {
                        P.SessionStorage.setItem(P.CONST.SESSION_FACEBOOK_ID, e.facebook_id),
                        P.SessionStorage.setItem(P.CONST.SESSION_FACEBOOK_TOKEN, e.facebook_token),
                        window.location.href = "/join/register/facebook/";
                    };
                P.currentUser.login(e, t, n);
            },
            resize: function()
            {
                this._$_content || (this._$content = this.$(".contentWrapper"), this._contentHeight = this._$content.height());
                var i = this.$(".homeUnauthImage"),
                    o = this._contentHeight;
                i.width();
                var s = i.height(),
                    r = $(window).height(),
                    a = $(window).width(),
                    l = this._minWindowHeight,
                    u = t,
                    c = this._minImageHeight;
                if (a < u)
                {
                    var d = a / u,
                        h = Math.min(t * d, 855);
                    i.css({
                        height: "auto",
                        width: h + "px"
                    });
                }
                if (r < l)
                {
                    var p = r - o - 100;
                    p < c ? i.addClass(e) : (i.removeClass(e), i.css({
                        width: "auto",
                        height: p + "px"
                    }));
                }
                else
                {
                    i.css({
                        height: "auto",
                        width: "auto"
                    }),
                    i.removeClass(e);
                }
                s || (s = n);
                var f = r - s - this._contentHeight;
                f >= 50 ? this._$content.css("marginTop", f / 2) : this._$content.css("marginTop", 50);
            }
        });
    }),
P.Module.define("UnblockButton", [],
    function()
    {
        return P.Module.extend({
            events: {
                click: "onClick"
            },
            onUserUnblockSuccess: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "block_unblock_user_success",
                            name: e.options.full_name,
                            action: "unblocked"
                        }
                    };
                _.extend(t.options, e.options.dialog_options),
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM, e.onUnblockConfirm);
                    });
            },
            onUnblockConfirm: function()
            {
                this.destroy();
            },
            onClick: function()
            {
                P.trackGAEvent("user_unblock", P.CONST.GA_ACTION_CLICK);
                var e = this,
                    t = this.options.user_id;
                this.showLoading();
                var n = {
                    blocked_user_id: this.options.user_id
                },
                    i = new P.Resource("UserBlockResource", n);
                i.call("delete", {
                    success: function()
                    {
                        P.trackGAEvent("user_unblock", P.CONST.GA_ACTION_SUCCESS),
                        P.pubsub.publish(t, P.CONST.PUBSUB_TOPIC_USER_UNBLOCKED),
                        e.onUserUnblockSuccess();
                    },
                    error: function(e)
                    {
                        P.showError(e.message),
                        P.trackGAEvent("user_unblock", P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        e.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("UploadPin", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.childListen(P.CONST.EVENT_PIN_CREATE_OPENED, this.onChildPinCreateOpened);
            },
            onChildPinCreateOpened: function()
            {
                this.destroy();
            }
        });
    }),
P.Module.define("User", [],
    function()
    {
        var e = "followFriendsItem";
        return P.Module.extend({
            events: {
                "click .dismiss": "onDismissClick",
                click: "onClick"
            },
            getLoadingSpinnerOptions: function()
            {
                return this.options.view_type === e ? {
                    size: P.Spinner.Size.SMALL
                } : {};
            },
            getProfileImage: function()
            {
                var e;
                switch (this.options && this.options.view_type)
                {
                    case "send_pin":
                        e = this.$(".profileImage");
                        break;
                    default:
                        return;
                }
                return e.attr("src");
            },
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_USER_FOLLOW] = this.onUserFollow;
                var t = this.getUserId();
                this.pubsubSubscribe(t, e);
            },
            onUserFollow: function()
            {
                this.options.view_type === e && this.$el.addClass("followed"),
                this.triggerEvent(P.CONST.EVENT_USER_FOLLOW, null, !0);
            },
            onDismissClick: function()
            {
                this.triggerEvent(P.CONST.EVENT_DISMISS, null, !0);
            },
            getUserId: function()
            {
                return this.data && this.data.id;
            },
            onClick: function()
            {
                "send_pin" === this.options.view_type && this.triggerEvent(P.CONST.EVENT_USER_CLICK, null, !0);
            }
        });
    }),
P.Module.define("UserBadge", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("UserBlock", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .cancelButton": "onCancelButtonClick"
            },
            onContentReady: function()
            {
                this.form = new P.Form(this.$("form")),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick);
            },
            onButtonClick: function(e)
            {
                var t = e.target;
                if (t)
                {
                    var n = this.options.blocked_by_me ? "user_unblock" : "user_block";
                    "cancelButton" === t.id ? P.trackGAEvent(n, P.CONST.GA_ACTION_CLICK_CANCEL) : "submitButton" === t.id && P.trackGAEvent(n, P.CONST.GA_ACTION_CLICK_SUBMIT);
                }
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.blockUser();
            },
            onUserBlockSuccess: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "block_unblock_user_success",
                            name: e.options.full_name,
                            action: "blocked"
                        }
                    };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM, e.onBlockConfirm);
                    });
            },
            onBlockConfirm: function()
            {
                P.ModalManager.instance().removeAllModals();
                var e = P.getCurrentUrl().split("/") || [];
                e[1] && e[1] === this.options.username && this.navigate("/");
            },
            blockUser: function()
            {
                var e = this,
                    t = this.getChildById("submitButton"),
                    n = this.options.user_id;
                t.showLoading();
                var i = {
                    blocked_user_id: n
                },
                    o = this.options.blocked_by_me ? "delete" : "create",
                    s = new P.Resource("UserBlockResource", i),
                    r = this.options.blocked_by_me ? "user_unblock" : "user_block";
                s.call(o, {
                    success: function()
                    {
                        P.trackGAEvent(r, P.CONST.GA_ACTION_SUCCESS),
                        P.pubsub.publish(e.options.user_id, P.CONST.PUBSUB_TOPIC_USER_BLOCKED),
                        e.onUserBlockSuccess();
                    },
                    error: function(e)
                    {
                        P.showError(e.message),
                        P.trackGAEvent(r, P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            },
            onCancelButtonClick: function()
            {
                this.destroy();
            }
        });
    }),
P.Module.define("UserBoardInvites", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.destroyIfEmpty(),
                this.pagedGrid = this.getChildById("pagedGrid"),
                this.childListen(P.CONST.EVENT_CONTENT_CHANGED, this.onChildContentChanged);
            },
            onChildRemoved: function()
            {
                this.destroyIfEmpty();
            },
            onChildContentChanged: function()
            {
                this.pagedGrid.hasItems() || this.pagedGrid.destroy();
            },
            isEmpty: function()
            {
                return !this.children.length;
            }
        });
    }),
P.Module.define("UserBoards", ["BoardCreateRep", "Board"],
    function(e, t)
    {
        var n = P.CONST.BOARD_PRIVACY_SECRET,
            i = "publicBoardsGrid",
            o = "secretBoardsGrid",
            s = "createsecretrep";
        return P.Module.extend({
            onContentReady: function()
            {
                this.numSecretBoards = this.numSecretBoards || parseInt(this.options.secret_board_count, 10),
                this.numCreateSecretBoardRep = 0;
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_BOARD_CREATED] = this.onBoardCreated,
                e[P.CONST.PUBSUB_TOPIC_BOARD_DELETED] = this.onBoardDeleted,
                e[P.CONST.PUBSUB_TOPIC_BOARD_UPDATED] = this.onBoardUpdated,
                this.extraData.isOwnProfile && (e[P.CONST.PUBSUB_TOPIC_BOARD_REMOVED_COLLABORATOR_SELF] = this.onBoardRemovedSelf),
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, e),
                this.extraData.isOwnProfile && (this.initializePublicBoardsSortManager(), this.addCreateSecretBoardReps());
            },
            initializePublicBoardsSortManager: function()
            {
                var e = this.getChildById(i),
                    t = this,
                    n = function(t)
                    {
                        var n = t.find(".Board"),
                            i = e.items.getChildByElement(n);
                        i.disable();
                    },
                    o = function(t)
                    {
                        var n = t.find(".Board"),
                            i = e.items.getChildByElement(n);
                        i.enable();
                    },
                    s = {
                        cancel: ".BoardCreateRep",
                        start: function(e, t)
                        {
                            n(t.item);
                        },
                        stop: function(e, t)
                        {
                            setTimeout(function()
                            {
                                o(t.item);
                            },
                                5);
                        },
                        update: function(e, n)
                        {
                            t.onPublicBoardsSortUpdate(e, n);
                        }
                    };
                e.items.initializeSortManager(s, "Board",
                    function(e)
                    {
                        return e.data && e.data.id;
                    });
            },
            onPublicBoardsSortUpdate: function()
            {
                var e = this.getChildById(i);
                this.saveBoardOrder(e.items.getSortOrder());
            },
            saveBoardOrder: function(e)
            {
                var t = "BoardsReorderResource",
                    n = {
                        board_ids: e
                    },
                    i = new P.Resource(t, n),
                    o = "user_boards_reorder";
                i.call("update", {
                    success: function()
                    {
                        P.trackGAEvent(o, P.CONST.GA_ACTION_SUCCESS);
                    },
                    error: function()
                    {
                        P.trackGAEvent(o, P.CONST.GA_ACTION_ERROR);
                    }
                });
            },
            addCreateSecretBoardReps: function()
            {
                if (this.extraData.isOwnProfile)
                {
                    for (var e, t = this.getChildById(o), i = this.numSecretBoards + this.numCreateSecretBoardRep, r = i; r < P.CONST.MAX_SECRET_BOARDS; r++)
                    {
                        e = s + this.numCreateSecretBoardRep++,
                        this.addCreateBoardRep(e, n, t);
                    }
                }
            },
            removeCreateSecretBoardReps: function()
            {
                for (var e = this.getChildById(o), t = this.numCreateSecretBoardRep, n = 0; n < t; n++)
                {
                    e.items.removeChildById(s + n),
                    this.numCreateSecretBoardRep--;
                }
            },
            onBoardDeleted: function(e, t, i)
            {
                i.privacy && i.privacy === n && (this.numSecretBoards--, this.addCreateSecretBoardReps());
            },
            onBoardCreated: function(e, s, r)
            {
                var a, l = r,
                    u = l.id,
                    c = l.privacy,
                    d = c === n ? o : i,
                    h = this.getChildById(d),
                    p = new t({
                        options: {
                            show_board_context: !1
                        },
                        resource: {
                            name: "BoardResource",
                            options: {
                                board_id: u
                            }
                        }
                    }),
                    f = this;
                c === n ? (this.numSecretBoards++, this.removeCreateSecretBoardReps(), a = function()
                {
                    f.addCreateSecretBoardReps();
                }) : a = function()
                {
                },
                h.items.appendChild(p),
                p.render(a);
            },
            onBoardUpdated: function(e, t, n)
            {
                n === P.CONST.PUBSUB_MESSAGE_BOARD_SET_PUBLIC && (this.numSecretBoards--, this.render());
            },
            addCreateBoardRep: function(t, i, o)
            {
                if (!o.items.getChildById(t))
                {
                    var s = new e({
                        id: t,
                        options: {
                            num_secret_boards: this.numSecretBoards,
                            secret: i === n
                        }
                    });
                    s.render(function()
                    {
                        o.items.appendChild(s);
                    });
                }
            },
            onBoardRemovedSelf: function()
            {
                this.render();
            }
        });
    }),
P.Module.define("UserChangePassword", [],
    function()
    {
        var e = "changePasswordSubmit";
        return P.Module.extend({
            onContentReady: function()
            {
                this.$form = this.$("form"),
                this.form = new P.Form(this.$form, {
                    old: [P.Validator.Required(), P.Validator.Password()],
                    "new": [P.Validator.Required(), P.Validator.Password()],
                    new_confirm: [P.Validator.Required(), P.Validator.Password()]
                }),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
                var e = this.getChildById("forgotPasswordButton");
                this.listen(e, P.CONST.EVENT_BUTTON_CLICK, this.onForgotPasswordClick);
            },
            onSubmitValidated: function(t)
            {
                var n = this.getChildById(e);
                n.showLoading(!0),
                t.errors[0] || this.changePassword();
            },
            changePassword: function()
            {
                var t = this;
                this.hideLoading(!0);
                var n = function()
                {
                    var n = t.getChildById(e);
                    n.hideLoading();
                },
                    i = function()
                    {
                        if (t.isInModal())
                        {
                            var e = {
                                name: "ConfirmDialog",
                                options: {
                                    template: "change_password_success"
                                }
                            };
                            P.loadModule(e,
                                function(e)
                                {
                                    t.showInModal(e),
                                    t.listen(e, P.CONST.EVENT_CONFIRM, t.destroy);
                                });
                        }
                        else
                        {
                            t.navigate("/");
                        }
                    },
                    o = $("form", this.$el),
                    s = new P.Resource("UserPasswordResource", {
                        old: o.find("[name=old]").val(),
                        "new": o.find("[name=new]").val(),
                        new_confirm: o.find("[name=new_confirm]").val()
                    });
                s.call("update", {
                    success: i,
                    complete: n
                });
            },
            onForgotPasswordClick: function()
            {
                var e = this;
                P.trackGAEvent("forgot_password", P.CONST.GA_ACTION_CLICK),
                this.showLoading();
                var t = new P.Resource("ForgotPasswordResource", {
                    username_or_email: P.currentUser.attributes.username
                }),
                    n = function()
                    {
                        P.trackGAEvent("forgot_password", P.CONST.GA_ACTION_SUCCESS);
                        var t = {
                            name: "ConfirmDialog",
                            options: {
                                template: "change_password"
                            }
                        };
                        P.loadModule(t,
                            function(t)
                            {
                                e.showInModal(t),
                                e.listen(t, P.CONST.EVENT_CONFIRM, e.destroy);
                            });
                    },
                    i = function()
                    {
                        e.hideLoading();
                    },
                    o = function()
                    {
                        P.trackGAEvent("forgot_password", P.CONST.GA_ACTION_ERROR);
                    };
                t.call("create", {
                    success: n,
                    complete: i,
                    error: o
                });
            }
        });
    }),
P.Module.define("UserCommonPins", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("UserDropdown", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate),
                this.$(".switchToOld").click(_.bind(this.onSwitch, this));
            },
            onChildNavigate: function(e)
            {
                e.data.$el && e.data.$el.hasClass("addPin") && (this.onClickAddPin(), e.stopPropagation());
            },
            onSwitch: function(e)
            {
                e.stopPropagation(),
                e.preventDefault(),
                this.$el.empty(),
                this.triggerEvent("switchToOld", e.target.href, !0);
            },
            onClickAddPin: function()
            {
                var e = this,
                    t = {
                        name: "AddPin",
                        options: {
                            shrinkToFit: !0,
                            dropdown_style: !1
                        }
                    };
                return this.showLoading(),
                P.loadModule(t,
                    function(t)
                    {
                        P.trackGAEvent("pin_add", P.CONST.GA_ACTION_OPEN_MODAL),
                        e.hideLoading(),
                        e.showInModal(t);
                    }),
                !1;
            }
        });
    }),
P.Module.define("UserEdit", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {
                    first_name: [P.Validator.Required()],
                    username: [P.Validator.Required()],
                    about: [P.Validator.Length({
                        max: P.CONST.MAX_CHARS_FOR_USER_DESCRIPTION
                    })]
                };
                this.data.is_partner && (e.business_name = [P.Validator.Required()]),
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form"), e),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.saveProfile();
            },
            getFormData: function()
            {
                var e = this.$("form").serializeArray(),
                    t = {};
                return _.each(e,
                    function(e)
                    {
                        t[e.name] = e.value;
                    }),
                t;
            },
            getSaveResource: function(e)
            {
                return new P.Resource("UserSettingsResource", e);
            },
            saveProfile: function()
            {
                var e = this.getFormData(),
                    t = this.getChildById("submitButton"),
                    n = this,
                    i = this.extraData.currentUsername,
                    o = e.username && i !== e.username;
                t.showLoading();
                var s = this.getSaveResource(e);
                s.call("update", {
                    success: function(i)
                    {
                        var s;
                        if (t.hideLoading(), i.resource_response.error)
                        {
                            i.resource_response.message && (s = {
                                message: i.resource_response.message
                            });
                        }
                        else
                        {
                            var r = n.isInModal() && !o;
                            if (r)
                            {
                                P.pubsub.publish(n.options.user_id, P.CONST.PUBSUB_TOPIC_USER_UPDATED),
                                n.destroy();
                            }
                            else
                            {
                                var a = "/" + e.username + "/";
                                n.navigate(a);
                            }
                        }
                    },
                    error: function(e)
                    {
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("UserEditEmail", [],
    function()
    {
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                this.$form = this.$("form"),
                this.form = new P.Form(this.$form, {
                    email: [P.Validator.Required()]
                }),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.updateEmail();
            },
            updateEmail: function()
            {
                var e = this,
                    t = function(t)
                    {
                        if (t)
                        {
                            var n = t.resource_response;
                            if (n && !n.error)
                            {
                                if (e.isInModal())
                                {
                                    var i = P.string("emailUpdated");
                                    e.options.sendVerifyEmail && (i = P.CONST.PUBSUB_MESSAGE_USER_EMAIL_UPDATED),
                                    P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_USER_UPDATED, i),
                                    e.destroy();
                                }
                                return;
                            }
                        }
                    },
                    n = $("form", this.$el),
                    i = new P.Resource("UserSettingsResource", {
                        email: n.find("[name=email]").val()
                    });
                i.call("update", {
                    success: t
                });
            }
        });
    }),
P.Module.define("UserEditVerifyWebsite", [],
    function()
    {
        return P.Module.extend({
            events: {
                'keyup input[name="website_url"]': "onInput",
                'input input[name="website_url"]': "onInput"
            },
            onContentReady: function()
            {
                this.originalWebsite = this.data.website_url;
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_USER_UPDATED] = this.onUserUpdated,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, e);
                var t = this.getChildById("verifyWebsite");
                this.listen(t, P.CONST.EVENT_BUTTON_CLICK, this.onClick);
            },
            onUserUpdated: function()
            {
                this.render();
            },
            onInput: function(e)
            {
                var t = $(e.target).val(),
                    n = this.getChildById("verifyWebsite"),
                    i = this.options.domain_verified && t === this.originalWebsite;
                this.$(".verifiedDomainContainer").toggleClass("hidden", !i),
                this.$(".verifyButton").toggleClass("hidden", i),
                t ? n.enable() : n.disable();
            },
            showModal: function(e)
            {
                this.showLoading();
                var t = this,
                    n = {
                        name: "DomainVerify",
                        resource: {
                            name: "DomainVerifyResource",
                            options: {
                                domain: e
                            }
                        },
                        options: {
                            domain: e
                        }
                    };
                P.loadModule(n,
                    function(e)
                    {
                        t.hideLoading(),
                        t.showInModal(e);
                    });
            },
            onClick: function()
            {
                var e = this.$('input[name="website_url"]').val();
                if (e === this.originalWebsite)
                {
                    return this.showModal(e),
                    void 0;
                }
                var t = this,
                    n = this.getChildById("verifyWebsite");
                n.showLoading();
                var i = new P.Resource("UserSettingsResource", {
                    website_url: e
                });
                i.call("update", {
                    success: function()
                    {
                        P.pubsub.publish(t.options.user_id, P.CONST.PUBSUB_TOPIC_USER_UPDATED),
                        t.showModal(e);
                    },
                    error: function(e)
                    {
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        n.hideLoading();
                    }
                });
            }
        });
    }),
P.Module.define("UserFollowButton", ["ui.FollowButton"],
    function(e)
    {
        return e.extend({
            getResourceId: function()
            {
                return this.options.user_id;
            },
            getFollowResource: function()
            {
                return new P.Resource("UserFollowResource", {
                    user_id: this.getResourceId()
                });
            },
            getFollowClass: function()
            {
                return this.options.follow_class;
            }
        });
    }),
P.Module.define("UserInfoBar", ["InfoBarBase"],
    function(e)
    {
        return e.extend({
            events: {},
            onContentReady: function()
            {
                var t = {};
                t[P.CONST.PUBSUB_TOPIC_USER_FOLLOW] = this.onFollowerChange,
                t[P.CONST.PUBSUB_TOPIC_USER_UNFOLLOW] = this.onFollowerChange,
                this.pubsubSubscribe(this.options.user_id, t);
                var n = {};
                n[P.CONST.PUBSUB_TOPIC_BOARD_CREATED] = this.onBoardCountUpdate,
                n[P.CONST.PUBSUB_TOPIC_BOARD_DELETED] = this.onBoardCountUpdate,
                n[P.CONST.PUBSUB_TOPIC_BOARD_UPDATED] = this.onBoardCountUpdate,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, n),
                e.prototype.onContentReady.call(this);
            },
            onBoardCountUpdate: function(e, t, n)
            {
                n.privacy !== P.CONST.BOARD_PRIVACY_SECRET && this.render();
            },
            onFollowerChange: function()
            {
                this.render();
            }
        });
    }),
P.Module.define("UserMenu", ["DropdownButton"],
    function(e)
    {
        return e.extend({
            onContentReady: function()
            {
                var t = this.extraData.userId;
                if (t)
                {
                    var n = {};
                    n[P.CONST.PUBSUB_TOPIC_USER_UPDATED] = this.onUserUpdated,
                    this.pubsubSubscribe(this.extraData.userId, n);
                }
                e.prototype.onContentReady.apply(this, arguments);
            },
            onUserUpdated: function()
            {
                this.render();
            },
            setSticky: function(e)
            {
                this._dropdown.options.sticky = e;
            }
        });
    }),
P.Module.define("UserNews", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.destroyIfEmpty();
            },
            onChildRemoved: function()
            {
                this.destroyIfEmpty() || this.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
            }
        });
    }),
P.Module.define("UserProfileContent", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                if (!this.data.board_count && !this.data.secret_board_count)
                {
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_BOARD_CREATED] = this.onFirstBoardCreated,
                    this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, e);
                }
            },
            onFirstBoardCreated: function()
            {
                this.pubsubUnsubscribe(P.CONST.PUBSUB_CHANNEL_CURRENT_USER, P.CONST.PUBSUB_TOPIC_BOARD_CREATED),
                this.render();
            }
        });
    }),
P.Module.define("UserProfileHeader", [],
    function()
    {
        return P.Module.extend({
            events: {},
            initialize: function()
            {
                this._resized = !1;
            },
            _resizeTextIfReady: function()
            {
                !this._resized && this.inDom && this.contentReady && this.$(".userProfileHeaderBio").overflowingText();
            },
            onContentReady: function()
            {
                if (this._resizeTextIfReady(), this.options.user_id)
                {
                    var e = {};
                    e[P.CONST.PUBSUB_TOPIC_USER_UPDATED] = this.onUserUpdated,
                    this.pubsubSubscribe(this.options.user_id, e);
                }
                if (this.options.report_user_spam && !this.data.blocked_by_me)
                {
                    P.ModalManager.instance().removeAllModals();
                    var t = {
                        name: "FlagUser",
                        options: {
                            full_name: this.data.full_name,
                            first_name: this.data.first_name,
                            blocked_by_me: this.data.blocked_by_me,
                            user_id: this.data.id,
                            username: this.data.username,
                            hide_other_field: !0
                        }
                    },
                        n = this;
                    P.loadModule(t,
                        function(e)
                        {
                            n.showInModal(e);
                        });
                }
            },
            onAddedToDom: function()
            {
                this._resizeTextIfReady();
            },
            onUserUpdated: function()
            {
                this.render();
            }
        });
    }),
P.Module.define("UserProfileImageUploader", [],
    function()
    {
        return P.Module.extend({
            events: {},
            initialize: function()
            {
                _.bindAll(this, "onUpdateSuccess", "onUpdateError");
            },
            onContentReady: function()
            {
                var e = this.getChildById("uploader");
                this.listen(e, P.CONST.EVENT_UPLOAD_SUCCESS, this.onUploadSuccess),
                this.listen(e, P.CONST.EVENT_UPLOAD_ERROR, this.onUploadError);
            },
            onUploadSuccess: function(e)
            {
                P.trackGAEvent("user_profile_image_upload", P.CONST.GA_ACTION_SUCCESS),
                this.imageUrl = e.data.image_url,
                this.updateUserProfileImage();
            },
            onUploadError: function(e)
            {
                P.trackGAEvent("user_profile_image_upload", P.CONST.GA_ACTION_ERROR),
                P.showError(P.string(e.data));
            },
            getUserSettingsResource: function()
            {
                return new P.Resource("UserSettingsResource", {
                    profile_image_url: this.imageUrl
                });
            },
            updateUserProfileImage: function()
            {
                var e = this.getUserSettingsResource();
                e.call("update", {
                    success: this.onUpdateSuccess,
                    error: this.onUpdateError
                });
            },
            onUpdateSuccess: function(e)
            {
                P.pubsub.publish(this.options.user_id, P.CONST.PUBSUB_TOPIC_USER_UPDATED, e.resource_response),
                this.destroy();
            },
            onUpdateError: function()
            {
            }
        });
    }),
P.Module.define("UserProfilePage", [],
    function()
    {
        return P.Module.extend({
            events: {},
            _tabs_to_resource: {
                boards: "BoardsResource",
                pins: "UserPinsResource",
                likes: "UserLikesResource",
                followers: "UserFollowersResource",
                following: "UserFollowingResource"
            },
            onAddedToDom: function()
            {
                this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate);
            },
            onRemovedFromDom: function()
            {
                this._removeListeners();
            },
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_USER_BLOCKED] = this.render,
                e[P.CONST.PUBSUB_TOPIC_USER_UNBLOCKED] = this.render,
                this.pubsubSubscribe(this.data.id, e);
            },
            onChildNavigate: function(e)
            {
                P.log("UserProfilePage got navigate event from child", e.target, "for url:", e.data.url);
                var t = P.router.resolve(e.data.url);
                if (t)
                {
                    var n = t.module,
                        i = t.options,
                        o = t.resource,
                        s = i.username;
                    if (this.contentReady && n === this.className && s === this.options.username)
                    {
                        this.setOptions(i),
                        this.setResource(o);
                        var r = this.$el.height();
                        this.$el.css("min-height", r);
                        var a = this.getScrollableElement(),
                            l = a.scrollTop(),
                            u = this,
                            c = i.tab,
                            d = this.getChildByModuleName("UserProfileContent");
                        d.setOptions({
                            tab: c
                        }),
                        d.render(function()
                        {
                            u.$el.css("min-height", "");
                            var e = a.height(),
                                t = u.$el.positionAncestor(a).top,
                                n = u.$el.height(),
                                i = l + e - n + t;
                            i > 0 && (u.$el.css("min-height", n + i), a.scrollTop(l));
                        }),
                        e.data.handled = !0;
                    }
                }
            }
        });
    }),
P.Module.define("UserRecentActivity", [],
    function()
    {
        return P.Module.extend({
            events: {
                "mouseenter .username": "onUsernameMouseEnter",
                "mouseout .username": "onUsernameMouseOut"
            },
            onContentReady: function()
            {
                this.destroyIfEmpty();
            },
            onAddedToDom: function()
            {
                _.each(this.$(".recentActivityRow"),
                    function(e)
                    {
                        var t = $(e),
                            n = t.attr("href"),
                            i = t.data("link_url");
                        n !== i && t.attr("href", i);
                    }),
                this.destroyIfEmpty();
            },
            isEmpty: function()
            {
                return this.contentReady && this.inDom && !this.$(".recentActivityRow:visible").length;
            },
            onUsernameMouseEnter: function(e)
            {
                var t = $(e.target).parents("a");
                this._originalUrl = t.attr("href");
                var n = $(e.target),
                    i = n.data("username");
                if (i)
                {
                    var o = "/" + i + "/";
                    t.attr("href", o);
                }
            },
            onUsernameMouseOut: function(e)
            {
                var t = this,
                    n = $(e.target).parents("a");
                n.attr("href", t._originalUrl);
            }
        });
    }),
P.Module.define("UserRegister", [],
    function()
    {
        var e = "hidden";
        return P.Module.extend({
            events: {
                "blur #userFirstName,#userLastName,#userEmail": "computeUsernameSuggestion",
                "keyup #userEmail": "computeUsernameSuggestion",
                "focus #userUserName": "onSuggestUsername",
                "keyup #userUserName": "onUsernameChanged",
                'change select[name="country"]': "onCountryChanged"
            },
            network: null,
            networkCredentials: {},
            usernameSuggestionResource: null,
            fieldValues: {},
            currentUsernameSuggestion: "",
            userModifiedUsername: !1,
            onCountryChanged: function(t)
            {
                var n = this.$(".termsWrapper"),
                    i = this.$(".helpText");
                "FR" === $(t.target).val() ? (n.removeClass(e), i.addClass(e)) : (n.addClass(e), i.removeClass(e));
            },
            onContentReady: function()
            {
                if (P.currentUser.isAuthenticated())
                {
                    return this.redirect(),
                    void 0;
                }
                var e = {
                    first_name: [P.Validator.Required()],
                    username: [P.Validator.Required()],
                    email: [P.Validator.Required(), P.Validator.Email()],
                    password: [P.Validator.Password()],
                    gender: [P.Validator.Required()],
                    country: []
                };
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form"), e),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated);
                var t = this.options.network && !this.options.network_data;
                t && this.fetchDataAndPopulateForm(this.options.network),
                this.extraData.show_username_suggestion && (this.fieldValues = this.getFieldValues(), this.currentUsernameSuggestion = this.$("#userUserName").val(), this.currentUsernameSuggestion && this.addUsernameAsSuggestionMessage());
            },
            getFieldValues: function()
            {
                var e = {
                    first_name: this.$("#userFirstName").val(),
                    last_name: this.$("#userLastName").val()
                },
                    t = this.$("#userEmail").val();
                return t.match("@") && (e.email = t.replace(/@.*/, "@")),
                e;
            },
            computeUsernameSuggestion: function()
            {
                if (this.extraData.show_username_suggestion && !this.userModifiedUsername)
                {
                    var e = this.getFieldValues();
                    if (!_.isEqual(this.fieldValues, e))
                    {
                        this.fieldValues = e;
                        var t = _.extend({},
                            this.fieldValues, {
                                limit: 1
                            });
                        null == this.usernameSuggestionResource && (this.usernameSuggestionResource = new P.Resource("UsernameSuggestionResource", t));
                        var n = this;
                        this.usernameSuggestionResource.options = t,
                        this.usernameSuggestionResource.call("get", {
                            success: function(e)
                            {
                                n.currentUsernameSuggestion = e.resource_response.data[0];
                            },
                            error: function()
                            {
                            }
                        });
                    }
                }
            },
            onSuggestUsername: function()
            {
                if (this.extraData.show_username_suggestion && !this.userModifiedUsername && this.currentUsernameSuggestion)
                {
                    var e = this.$("#userUserName");
                    e.val() !== this.currentUsernameSuggestion && (e.val(this.currentUsernameSuggestion), this.form.validateField(e), this.addUsernameAsSuggestionMessage());
                }
            },
            onUsernameChanged: function()
            {
                if (this.extraData.show_username_suggestion)
                {
                    var e = this.$("#userUserName");
                    e.val() ? this.currentUsernameSuggestion !== e.val() && (this.userModifiedUsername = !0, this.removeUsernameAsSuggestionMessage()) : (this.userModifiedUsername = !1, this.computeUsernameSuggestion(), this.removeUsernameAsSuggestionMessage());
                }
            },
            addUsernameAsSuggestionMessage: function()
            {
                var e = this.$("#userUserName");
                if (0 === e.nextAll(".formHelpMessage").length)
                {
                    var t = P.string("suggestedUsername");
                    e.after('<p class="formHelpMessage">' + t + "</p>");
                }
            },
            removeUsernameAsSuggestionMessage: function()
            {
                var e = this.$("#userUserName"),
                    t = e.nextAll(".formHelpMessage");
                t.remove();
            },
            populateForm: function(e)
            {
                if (this.options.network_data = e, this.extraData.show_username_suggestion)
                {
                    var t = {
                        first_name: e.first_name,
                        last_name: e.last_name,
                        email: e.email,
                        social_username: e.username,
                        limit: 1
                    };
                    this.resource = new P.Resource("UsernameSuggestionResource", t);
                }
                var n = this,
                    i = function()
                    {
                        n.hideLoading();
                    };
                this.render(i, i);
            },
            fetchDataAndPopulateForm: function(e)
            {
                var t = this;
                e === P.SocialConnect.FACEBOOK && (this.showLoading(), P.trackRegisterAction("register_facebook"), P.FBEnsureInit(function()
                {
                    P.FB.getLoginStatus(function(e)
                    {
                        if (e.authResponse)
                        {
                            var n = ["picture", "id", "first_name", "last_name", "email", "username", "gender"],
                                i = "/me?fields=" + n.join(",");
                            P.FB.api(i,
                                function(e)
                                {
                                    e && !e.error ? (e.picture && e.picture.data && e.picture.data.url && !e.picture.data.is_silhouette && (e.image_url = e.picture.data.url), t.populateForm(e)) : t.hideLoading();
                                });
                        }
                        else
                        {
                            t.hideLoading();
                        }
                    },
                        !0);
                }));
            },
            onSubmitValidated: function(e)
            {
                if (!e.errors[0])
                {
                    var t = this.getChildById("submitButton"),
                        n = this,
                        i = this.extraData && this.extraData.networkCredentials ? this.extraData.networkCredentials : {},
                        o = _.extend({},
                            this.getFormData(), i),
                        s = this.getResource(o),
                        r = P.SessionStorage.getItem(P.CONST.SESSION_FACEBOOK_ID),
                        a = P.SessionStorage.getItem(P.CONST.SESSION_FACEBOOK_TOKEN);
                    r && (o.facebook_id || (o.facebook_id = r), P.SessionStorage.removeItem(P.CONST.SESSION_FACEBOOK_ID)),
                    a && (o.facebook_token || (o.facebook_token = a), P.SessionStorage.removeItem(P.CONST.SESSION_FACEBOOK_TOKEN)),
                    this.options.network !== P.SocialConnect.FACEBOOK || o.facebook_token || (P.log("ERROR", "facebook token wasn't set"), o.facebook_token = P.FB.getAccessToken()),
                    t.showLoading(),
                    s.call("create", {
                        success: function(e)
                        {
                            P.SessionStorage.removeItem(P.CONST.SESSION_KEY_INVITE_FOLLOW),
                            P.log("Login, successful", e),
                            _.defer(function()
                            {
                                n.redirect();
                            });
                        },
                        error: function(e, t)
                        {
                            P.showError(e.message);
                            var i = [],
                                s = [];
                            _.each(o,
                                function(e, t)
                                {
                                    e ? s.push(t) : i.push(t);
                                });
                            var r = window.navigator,
                                a = {
                                    error_code: e.code,
                                    http_status: e.http_status,
                                    userAgent: r.userAgent,
                                    platform: r.platform,
                                    message: "Sign up error: " + e.message,
                                    extraData: {
                                        emptyKeys: i,
                                        keys: s,
                                        network: n.options.network
                                    },
                                    appVersion: P.AppVersion.currentVersion
                                };
                            t && (t.resource && t.resource.name && (a.resource = t.resource.name), t.error && t.error.api_error_code && (a.api_error_code = t.error.api_error_code)),
                            $.post("/_/_/report/error/", JSON.stringify(a));
                        },
                        complete: function()
                        {
                            t.hideLoading();
                        }
                    });
                }
            },
            redirect: function()
            {
                this.navigate("/");
            },
            getFormData: function()
            {
                var e = this.$("form").serializeArray(),
                    t = {};
                _.each(e,
                    function(e)
                    {
                        t[e.name] = "on" === e.value ? !0 : e.value;
                    });
                var n = P.SessionStorage.getItem(P.CONST.SESSION_KEY_INVITE_FOLLOW);
                return n && (n.invite_follow_board && (t.board_to_follow = n.invite_follow_board), n.invite_follow_user && (t.user_to_follow = n.invite_follow_user)),
                t;
            },
            getResource: function(e)
            {
                return new P.Resource("UserRegisterResource", e);
            }
        });
    }),
P.Module.define("UserRegisterPage", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("UserSettingsPage", [],
    function()
    {
        var e = "emailDisabled",
            t = "emailSettings",
            n = ["intro", "confirm", "delete"],
            i = "emailGlobalToggle";
        return P.Module.extend({
            events: {},
            onContentReady: function()
            {
                var e = {
                    email: [P.Validator.Email()]
                };
                this.data.is_partner && (e.contact_name = [P.Validator.Required()]),
                this.$form = this.$("form"),
                this.form = new P.Form(this.$form, e),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this.onButtonClick),
                this.childListen(P.CONST.EVENT_CHANGE, this.onChildChange);
            },
            onButtonClick: function(e)
            {
                var t = e.target,
                    n = t.id;
                switch (n)
                {
                    case "deleteAccount":
                        this.step = 0,
                        this.deleteAccountFlow();
                        break;
                    case "clearRecentSearches":
                        this.clearRecentSearches(e);
                        break;
                    case "clearSendPinHistory":
                        this.clearRecentSentPinContacts(e);
                }
            },
            onChildChange: function(e)
            {
                var t = e.target;
                t.id === i && (t.isChecked() ? this.enableEmails() : this.confirmDisableEmails());
            },
            clearRecentSearches: function(e)
            {
                var t = e.target;
                t.disable();
                var n = new P.Resource("TypeaheadClearRecentResource");
                n.call("delete", {
                    error: function()
                    {
                        t.enable();
                    }
                });
            },
            clearRecentSentPinContacts: function(e)
            {
                var t = e.target;
                t.disable();
                var n = new P.Resource("RecentContactsResource");
                n.call("delete", {
                    error: function()
                    {
                        t.enable();
                    }
                });
            },
            deleteAccountFlow: function()
            {
                var e = n[this.step];
                "delete" === e ? this.deleteAccount() : (this.showDeleteAccountStep(e), this.step++);
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.save();
            },
            navigateToUserProfilePage: function(e)
            {
                var t = "/" + e + "/";
                this.navigate(t);
            },
            save: function()
            {
                var e = this,
                    t = this.$form.serializeArray(),
                    n = {};
                _.each(t,
                    function(e)
                    {
                        n[e.name] = "on" === e.value ? !0 : e.value;
                    }),
                this.$form.find("input[type=checkbox]").each(function()
                {
                    var e = $(this);
                    n[e.attr("name")] = "checked" === e.attr("checked");
                });
                var i = this.getChildById("submitButton"),
                    o = new P.Resource("UserSettingsResource", n),
                    s = function(t)
                    {
                        if (t && !t.resource_response.error)
                        {
                            var n = t.resource_response.data.username;
                            return e.navigateToUserProfilePage(n);
                        }
                    };
                i.showLoading(),
                o.call("update", {
                    success: s,
                    complete: function()
                    {
                        i.hideLoading();
                    }
                });
            },
            showDeleteAccountStep: function(e)
            {
                var t = this,
                    n = "delete_account_" + e,
                    i = {
                        name: "ConfirmDialog",
                        options: {
                            first_name: this.data.first_name,
                            template: n,
                            view_type: "wide"
                        }
                    };
                P.loadModule(i,
                    function(e)
                    {
                        t.showInModal(e),
                        t.listen(e, P.CONST.EVENT_CONFIRM, t.deleteAccountFlow);
                    });
            },
            deleteAccount: function()
            {
                var e = this;
                this.xhr = $.ajax({
                    cache: !1,
                    url: "/delete_user/",
                    dataType: "json",
                    type: "delete"
                }).done(function(t)
                {
                    "success" === t.status ? e.showDeleteAccountStep("success") : P.showError(P.string("errorMessage"));
                }).fail(function()
                {
                    P.showError(P.string("errorMessage"));
                });
            },
            confirmDisableEmails: function()
            {
                var e = this,
                    t = {
                        name: "ConfirmDialog",
                        options: {
                            template: "disable_emails_confirm"
                        }
                    };
                P.loadModule(t,
                    function(t)
                    {
                        e.showInModal(t),
                        e.listen(t, P.CONST.EVENT_CONFIRM,
                            function()
                            {
                                e.disableEmails(),
                                e.removeListener(n);
                            });
                        var n = e.listen(t, P.CONST.EVENT_DESTROYED,
                            function()
                            {
                                var e = this.getChildById(i);
                                e.setChecked(!0);
                            });
                    });
            },
            disableEmails: function()
            {
                this.setEmailsEnabled(!1);
            },
            enableEmails: function()
            {
                this.setEmailsEnabled(!0);
            },
            setEmailsEnabled: function(n)
            {
                var i = new P.Resource("UserSettingsResource", {
                    email_enabled: n
                }),
                    o = this.$("." + t);
                o.toggleClass(e, !n),
                i.call("update");
            }
        });
    }),
P.Module.define("UserSocialNetworkSettings", ["SocialNetworkSettingsBase"],
    function(e)
    {
        return e.extend({
            FB_PUBLISH_ACTIONS_PERMISSION: "publish_actions",
            initialize: function()
            {
                this.childListen("change", this.onChildChange);
            },
            fbConnectedAccountMatchesLoggedInAccount: function()
            {
                if (!this.extraData.facebookId)
                {
                    return !0;
                }
                var e = P.FB.getAuthResponse();
                return e ? this.extraData.facebookId === e.userID : !0;
            },
            _checkFbTimelinePermission: function(e)
            {
                var t = this;
                P.FB.api("/me/permissions",
                    function(n)
                    {
                        var i = n.data;
                        i && i[0][t.FB_PUBLISH_ACTIONS_PERMISSION] ? e.success && e.success() : e.error && e.error();
                    });
            },
            maybeRequestFbTimelinePermission: function(e)
            {
                if (!this.fbConnectedAccountMatchesLoggedInAccount())
                {
                    return P.showError(P.string("facebookAccountDoesntMatch")),
                    e.error && e.error(),
                    e.complete && e.complete(),
                    void 0;
                }
                var t = this;
                this._checkFbTimelinePermission({
                    success: function()
                    {
                        e.success && e.success(),
                        e.complete && e.complete();
                    },
                    error: function()
                    {
                        P.FB.login(function(n)
                        {
                            n.authResponse ? t._checkFbTimelinePermission(e) : e.error && e.error(),
                            e.complete && e.complete();
                        },
                            {
                                scope: t.FB_PUBLISH_ACTIONS_PERMISSION
                            });
                    }
                });
            },
            onChildChange: function(e)
            {
                var t = e.target,
                    n = t.isChecked(),
                    i = null;
                switch (t.id)
                {
                    case "facebookToggle":
                        if (!(n && !this.extraData.facebookUrl || !n && this.extraData.facebookUrl))
                        {
                            return;
                        }
                        i = P.SocialConnect.FACEBOOK,
                        n || this.getChildById("facebookTimelineToggle").setChecked(!1);
                        break;
                    case "facebookTimelineToggle":
                        if (!n || this.extraData.facebookTimelineEnabled)
                        {
                            return;
                        }
                        i = null;
                        break;
                    case "twitterToggle":
                        if (!(n && !this.extraData.twitterUrl || !n && this.extraData.twitterUrl))
                        {
                            return;
                        }
                        i = P.SocialConnect.TWITTER;
                        break;
                    case "googleToggle":
                        if (!(n && !this.extraData.connected_to_google || !n && this.extraData.connected_to_google))
                        {
                            return;
                        }
                        i = P.SocialConnect.GOOGLE;
                        break;
                    case "yahooToggle":
                        if (!(n && !this.extraData.connected_to_yahoo || !n && this.extraData.connected_to_yahoo))
                        {
                            return;
                        }
                        i = P.SocialConnect.YAHOO;
                        break;
                    default:
                        return;
                }
                this.showLoading(!0);
                var o = this,
                    s = {
                        success: function()
                        {
                            o.render();
                        },
                        error: function()
                        {
                            t.toggle();
                        },
                        complete: function()
                        {
                            o.hideLoading();
                        }
                    };
                i || "facebookTimelineToggle" !== t.id ? this.handleConnect(i, n, s) : (s.success = function()
                {
                },
                this.maybeRequestFbTimelinePermission(s));
            }
        });
    }),
P.Module.define("dev.API", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.Android", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.Apps", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.Footer", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
            }
        });
    }),
P.Module.define("dev.Goodies", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.Header", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.Hero", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.HomeContent", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.RichPinApplyForm", [],
    function()
    {
        return P.Module.extend({
            events: {
                'click input[name="input_type"]': "onFormatChange"
            },
            onContentReady: function()
            {
                var e = {
                    domain: [P.Validator.Required()]
                };
                this.formListener && this.removeListener(this.formListener),
                this.form = new P.Form(this.$("form"), e),
                this.formListener = this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.onSubmitValidated),
                this.options && "oembed" === this.options.link_type && this.$(".oembed-url").show();
            },
            onFormatChange: function(e)
            {
                "oembed" === e.target.value ? this.$(".oembed-url").show() : this.$(".oembed-url").hide();
            },
            onSubmitValidated: function(e)
            {
                e.errors[0] || this.submitApplication();
            },
            getFormData: function()
            {
                var e = this.$("form").serializeArray(),
                    t = {};
                return _.each(e,
                    function(e)
                    {
                        t[e.name] = e.value;
                    }),
                t;
            },
            getSaveResource: function(e)
            {
                return new P.Resource("RichPinApplyResource", e);
            },
            submitApplication: function()
            {
                var e = this.getFormData(),
                    t = this.getChildById("submitButton"),
                    n = this;
                t.showLoading();
                var i = this.getSaveResource(e);
                i.call("create", {
                    success: function(e)
                    {
                        var i;
                        t.hideLoading(),
                        e.resource_response.error ? e.resource_response.message && (i = {
                            message: e.resource_response.message
                        }) : n.showSuccessMessage();
                    },
                    error: function(e)
                    {
                        P.showError(e.message);
                    },
                    complete: function()
                    {
                        t.hideLoading();
                    }
                });
            },
            showSuccessMessage: function()
            {
                var e = {
                    name: "ConfirmDialog",
                    options: {
                        template: "richpin_apply_success"
                    }
                },
                    t = this;
                P.loadModule(e,
                    function(e)
                    {
                        t.listen(e, P.CONST.EVENT_DESTROYED,
                            function()
                            {
                                t.destroy();
                            }),
                        t.showInModal(e);
                    });
            }
        });
    }),
P.Module.define("dev.RichPinValidate", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("dev.RichPinValidateMovie", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("dev.RichPinValidateProduct", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("dev.RichPinValidateRecipe", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("dev.RichPinValidator", [],
    function()
    {
        return P.Module.extend({
            events: {
                "click .retrieveMetadata": "retrieve"
            },
            onContentReady: function()
            {
                this.$form = this.$("form"),
                this.linkValidator = new P.Validator($(".urlInput"), [P.Validator.URL()]),
                this.form = new P.Form(this.$form),
                this.listen(this.form, P.CONST.EVENT_SUBMIT_VALIDATED, this.retrieve);
                var e = $(".sidebar"),
                    t = $(".content"),
                    n = e.height(),
                    i = t.height();
                n > i && t.height(n),
                "1" === this.options.apply && this.showApplyDialog();
            },
            retrieve: function()
            {
                var e = this,
                    t = this.$form.serializeArray();
                return this.linkValidator.validate(function(n)
                {
                    if (n.errors.length)
                    {
                        var i = $(".urlInput").attr("error-message");
                        P.showError(i);
                    }
                    else
                    {
                        var o = encodeURIComponent(t[0].value);
                        this.getChildById("submitButton"),
                        e.navigate("/developer/rich_pins/validator/?link=" + o);
                    }
                }),
                !1;
            },
            showApplyDialog: function()
            {
                var e = this;
                P.loadModule({
                        name: "dev.RichPinApplyForm"
                    },
                    function(t)
                    {
                        e.showInModal(t, {});
                    });
            }
        });
    }),
P.Module.define("dev.RichPins", [],
    function()
    {
        return P.Module.extend({
            onContentReady: function()
            {
                this.setupRichPins();
            },
            onAddedToDom: function()
            {
                this.setupRichPins();
            },
            setupRichPins: function()
            {
                if (this.inDom && this.contentReady)
                {
                    var e = this,
                        t = this.$(".navigation"),
                        n = window.location.hash ? window.location.hash.substring(1) : "";
                    n && ($("a." + n, t).addClass("selected"), e.scrollToLocation("#" + n)),
                    this.$("a.anchorable", t).click(function()
                    {
                        $("a", t).removeClass("selected"),
                        $(this).addClass("selected");
                        var n = $(this).attr("href");
                        e.scrollToLocation(n);
                    });
                }
            },
            scrollToLocation: function(e)
            {
                var t = $(e).position();
                t && (t = t.top - 130, window.scrollTo(0, t));
            }
        });
    }),
P.Module.define("dev.Sidebar", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.Terms", [],
    function()
    {
        return P.Module.extend({
            events: {}
        });
    }),
P.Module.define("dev.UserDropdown", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("dev.UserMenu", ["DropdownButton"],
    function(e)
    {
        return e.extend({
            onContentReady: function()
            {
                e.prototype.onContentReady.apply(this, arguments);
                var t = $(".devProfile a").width() + 10;
                t = Math.max(t, 130),
                $(".devUserDropdown").width(t);
            }
        });
    }),
P.Module.define("dev.iOS", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("tutorials.BaseTutorialStep", [],
    function()
    {
        var e = "tutorialHighlight",
            t = "tutorialHighlightMask";
        return P.Module.extend({
            initialize: function()
            {
                this.childListen(P.CONST.EVENT_BUTTON_CLICK, this._onButtonClick),
                this.listen(P.Viewport, P.CONST.EVENT_RESIZE, _.bind(this.onResize, this));
            },
            setModalPosition: function(e, t, n)
            {
                var i = "VIEWPORT_MIDDLE";
                e && t && (i = "ANCHORED", this.modal.options.position_point = e, this.modal.options.anchor = t),
                this.modal.options.positionMode = i,
                this.modal.options.caret = !0,
                n && this.modal.positionModule();
            },
            onEnter: function(e)
            {
                e && e();
            },
            onShow: function(e)
            {
                e && e();
            },
            onExit: function(e)
            {
                e && e();
            },
            _onButtonClick: function(e)
            {
                var t = e.target;
                t && ("previousButton" === t.id ? (e.stopPropagation(), this.triggerEvent(P.CONST.EVENT_PREVIOUS, null, !0)) : "nextButton" === t.id && (e.stopPropagation(), this.triggerEvent(P.CONST.EVENT_NEXT, null, !0)));
            },
            ensurePath: function(e)
            {
                window.location.pathname !== e && this.navigate(e);
            },
            highlightedElements: {},
            cleanHighlightedElements: function()
            {
                $("." + e).remove(),
                this.highlightedElements = {};
            },
            _getModuleChildById: function(e, t)
            {
                var n = e._childrenIdMap[t];
                if (n)
                {
                    return n;
                }
                for (var i, o = 0,
                    s = e.children.length; o < s; o++)
                {
                    if (i = e.children[o], n = this._getModuleChildById(i, t))
                    {
                        return n;
                    }
                }
            },
            _getModuleChildrenByModuleName: function(e, t)
            {
                var n = [],
                    i = this;
                return _.each(e.children,
                    function(e)
                    {
                        e.className === t && n.push(e),
                        n = n.concat(i._getModuleChildrenByModuleName(e, t));
                    }),
                n;
            },
            _highlightModule: function(e, t)
            {
                return this._highlightElement(e.cid, e.$el, t);
            },
            _highlightElement: function(n, i, o)
            {
                var s;
                if (o)
                {
                    s = i.clone(),
                    s.$origin = i,
                    s.attr("id", n),
                    s.addClass(e),
                    this.highlightedElements[n] = s;
                    var r = $("body");
                    r.append(s);
                    var a = $('<div class="' + t + '"/>');
                    a.addClass(e),
                    r.append(a),
                    s.$mask = a,
                    this.positionClone(s);
                }
                else
                {
                    s = this.highlightedElements[n],
                    s && (s.remove(), delete this.highlightedElements[n]);
                }
                return s;
            },
            positionClone: function(e)
            {
                var t = e.$origin.offset();
                t = {
                    top: t.top,
                    left: t.left
                };
                var n = t.top - $(window).scrollTop();
                n > 0 && (t.top = n),
                e.css(t),
                e.$mask.css(t),
                e.$mask.css({
                    height: e.outerHeight(),
                    width: e.outerWidth()
                }),
                this.modal && this.modal.positionModule();
            },
            onResize: function()
            {
                _.each(this.highlightedElements, _.bind(this.positionClone, this));
            },
            onRemoved: function()
            {
                this.cleanHighlightedElements();
            }
        });
    }),
P.Module.define("tutorials.CategoriesStep", ["tutorials.BaseTutorialStep"],
    function(e)
    {
        return e.extend({
            onShow: function(e)
            {
                var t = this._getCategoriesDropdownButton(),
                    n = t.getDropdown();
                n.options.sticky = !0,
                t.showDropdown(_.bind(function()
                {
                    var n = this._highlightModule(t, !0);
                    this.setModalPosition("RIGHT_TOP", n, !0),
                    e && e();
                },
                    this));
            },
            onExit: function(e)
            {
                var t = this._getCategoriesDropdownButton(),
                    n = t.getDropdown();
                n.options.sticky = !1,
                t.hideDropdown(),
                e && e();
            },
            _getCategoriesDropdownButton: function()
            {
                return this._getModuleChildById(P.app, "categoriesDropdownButton");
            }
        });
    }),
P.Module.define("tutorials.ExampleTutorial", ["tutorials.BaseTutorial"],
    function(e)
    {
        return e.extend({
            onStep1: function()
            {
                var e = this._getModuleChildrenByModuleName(P.app, "Header")[0],
                    t = this._getModuleChildrenByModuleName(e, "Button"),
                    n = t[0];
                this._highlightModule(n, !0);
            }
        });
    }),
P.Module.define("tutorials.HomefeedStep", ["tutorials.BaseTutorialStep"],
    function(e)
    {
        return e.extend({
            onEnter: function(e)
            {
                this.ensurePath("/"),
                e && e();
            }
        });
    }),
P.Module.define("tutorials.PinterestLogoStep", ["tutorials.BaseTutorialStep"],
    function(e)
    {
        var t = "pinterestLogoStepBackground";
        return e.extend({
            onShow: function(e)
            {
                var n = this._getModuleChildrenByModuleName(P.app, "Header")[0],
                    i = n.getLogo(),
                    o = this._highlightElement(i.id, i, !0),
                    s = $("<div>");
                s.addClass(t),
                s.css({
                    top: o.offset().top - 60,
                    left: o.offset().left
                }),
                $("body").append(s),
                e && e();
            },
            onExit: function(e)
            {
                $("." + t).remove(),
                e && e();
            }
        });
    }),
P.Module.define("tutorials.ProfileStep", ["tutorials.BaseTutorialStep"],
    function(e)
    {
        return e.extend({
            onShow: function(e)
            {
                var t = this._getModuleChildById(P.app, "userMenu");
                t.setSticky(!0),
                t.showDropdown(_.bind(function()
                {
                    var n = this._highlightModule(t, !0);
                    n.width(t.$el.width()),
                    this.setModalPosition("LEFT_TOP", n, !0),
                    e && e();
                },
                    this));
            },
            onExit: function(e)
            {
                var t = this,
                    n = function()
                    {
                        e && e();
                        var n = t._getModuleChildById(P.app, "userMenu");
                        n.setSticky(!1),
                        n.hideDropdown();
                    },
                    i = "/" + P.currentUser.get("username") + "/";
                if (window.location.pathname === i)
                {
                    return n(),
                    void 0;
                }
                var o = {};
                o[P.CONST.PUBSUB_TOPIC_MAIN_MODULE_NEW] = function()
                {
                    t.pubsubUnsubscribe(P.CONST.PUBSUB_CHANNEL_MAIN_MODULE, P.CONST.PUBSUB_TOPIC_MAIN_MODULE_NEW),
                    _.delay(n, 1e3);
                },
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_MAIN_MODULE, o),
                this.getChildById("previousButton").disable(),
                this.getChildById("nextButton").disable(),
                this.navigate(i);
            }
        });
    }),
P.Module.define("tutorials.WelcomeStep", ["tutorials.BaseTutorialStep"],
    function(e)
    {
        return e.extend({});
    }),
P.Module.define("ui.Checkbox", [],
    function()
    {
        var e = "on",
            t = P.CONST.EVENT_CHANGE,
            n = "checked";
        return P.Module.extend({
            onContentReady: function()
            {
                this.$input = this.$el,
                "fancyToggle" === this.options.view_type && (this.$input = this.$("input"), this.$el.on("click", _.bind(this.onFancyToggleClick, this)));
            },
            onFancyToggleClick: function()
            {
                return this.toggle(),
                !1;
            },
            toggle: function()
            {
                this.setChecked(!this.options.checked);
            },
            setChecked: function(i)
            {
                i === this.options.checked || this.options.disabled || (this.options.checked = i, this.$el.toggleClass(e, i), this.$input.prop(n, i), this.triggerEvent(t, null, !0));
            },
            isChecked: function()
            {
                return !!this.options.checked;
            }
        });
    }),
P.Module.define("ui.FollowButton", ["Button"],
    function(e)
    {
        var t = "dim",
            n = "primary";
        return e.extend({
            getResourceId: function()
            {
                return null;
            },
            getFollowResource: function()
            {
                return null;
            },
            getFollowClass: function()
            {
                return n;
            },
            getUnfollowClass: function()
            {
                return t;
            },
            toggleState: function()
            {
                this.setState(!this.options.followed),
                this.trigger("toggleFollow"),
                this.getResourceId() && P.pubsub.publish(this.getResourceId(), this.options.followed ? P.CONST.PUBSUB_TOPIC_USER_FOLLOW : P.CONST.PUBSUB_TOPIC_USER_UNFOLLOW, !0);
            },
            setState: function(e)
            {
                this.$el.addClass(e ? this.getUnfollowClass() : this.getFollowClass()),
                this.$el.removeClass(e ? this.getFollowClass() : this.getUnfollowClass()),
                this.$el.text(this.options[e ? "unfollow_text" : "follow_text"]),
                this.options.followed = e;
            },
            toggleFollow: function()
            {
                var e = this.getFollowResource(),
                    t = this.options.followed ? "delete" : "create";
                if (!e)
                {
                    return P.log("ERROR", "No resource returned in `getFollowResource()`"),
                    void 0;
                }
                this.showLoading();
                var n = this.options.followed ? this.options.unfollow_ga_category : this.options.follow_ga_category,
                    i = this;
                e.call(t, {
                    success: function()
                    {
                        n && P.trackGAEvent(n, P.CONST.GA_ACTION_SUCCESS),
                        i.toggleState();
                    },
                    error: function(e)
                    {
                        P.showError(e.message),
                        n && P.trackGAEvent(n, P.CONST.GA_ACTION_ERROR);
                    },
                    complete: function()
                    {
                        i.hideLoading();
                    }
                });
            },
            onClick: function()
            {
                if (this.ensureAuthentication() && !this.options.is_me)
                {
                    var e = this.options.followed ? this.options.unfollow_ga_category : this.options.follow_ga_category;
                    return e && P.trackGAEvent(e, P.CONST.GA_ACTION_CLICK),
                    this.toggleFollow(),
                    !1;
                }
            }
        });
    }),
P.Module.define("ui.ImageCrop", [],
    function()
    {
        return P.Module.extend({
            events: {
                "mousedown .drag": "onStartDrag"
            },
            onAddedToDom: function()
            {
                this._positionIfReady();
            },
            onContentReady: function()
            {
                _.defaults(this.options, {
                    size: {
                        width: 222,
                        height: 150
                    },
                    padding: 60
                }),
                this.$holder = this.$(".holder"),
                this.$bg = this.$(".bg"),
                this.$help = this.$(".help"),
                this.$frame = this.$(".frame"),
                this.$mask = this.$(".mask"),
                this.$spinner = this.$(".spinner"),
                this.$holder.show().css("height", this.options.size.height + 2 * this.options.padding),
                this.options.help_text && this.$help.html(this.options.help_text),
                this._positionIfReady();
            },
            _positionIfReady: function()
            {
                if (!this._positioned && this.inDom && this.contentReady)
                {
                    this._positioned = !0;
                    var e = this._frameBounds = {
                        left: this.$holder.width() / 2 - this.options.size.width / 2,
                        width: this.options.size.width,
                        top: this.options.padding,
                        height: this.options.size.height
                    };
                    e.ratio = e.height / e.width,
                    this.$frame.css(e);
                    var t = this.$mask.children();
                    t.eq(0).css({
                        top: 0,
                        left: 0,
                        right: 0,
                        height: e.top
                    }),
                    t.eq(1).css({
                        top: e.top,
                        left: e.left + e.width,
                        right: 0,
                        height: e.height
                    }),
                    t.eq(2).css({
                        top: e.top + e.height,
                        left: 0,
                        right: 0,
                        bottom: 0
                    }),
                    t.eq(3).css({
                        top: e.top,
                        left: 0,
                        width: e.left,
                        height: e.height
                    }),
                    this.options.image_url && this.setImage(this.options.image_url);
                }
            },
            initImage: function()
            {
                if (!this.$img.height() || !this.$img.width())
                {
                    return _.delay(_.bind(this.initImage, this), 200),
                    void 0;
                }
                var e = this._imageBounds = {
                    nativeWidth: this.$img.width(),
                    nativeHeight: this.$img.height()
                };
                e.ratio = e.nativeHeight / e.nativeWidth,
                this.$img.addClass("in"),
                this._fitImage(),
                this._centerImage(),
                this._hideSpinner();
            },
            onStartDrag: function(e)
            {
                this._mousePosition = {
                    x: e.pageX,
                    y: e.pageY
                },
                this._startPosition = {
                    x: parseInt(this.$bg.css("left"), 10),
                    y: parseInt(this.$bg.css("top"), 10)
                },
                $("body").on({
                    "mousemove.ui-ImageCrop": _.bind(this.onDragging, this),
                    "mouseup.ui-ImageCrop": this.onStopDragging
                }),
                e.preventDefault();
            },
            onDragging: function(e)
            {
                e.preventDefault();
                var t = e.pageX - this._mousePosition.x,
                    n = e.pageY - this._mousePosition.y,
                    i = {
                        top: this._startPosition.y + n,
                        left: this._startPosition.x + t
                    };
                this._clampValues(i),
                this.$bg.css(i);
            },
            onStopDragging: function()
            {
                $("body").off("mousemove.ui-ImageCrop mouseup.ui-ImageCrop");
            },
            _clampValues: function(e)
            {
                e.top = Math.min(e.top, this._frameBounds.top),
                e.left = Math.min(e.left, this._frameBounds.left),
                e.top + this._imageBounds.height < this._frameBounds.top + this._frameBounds.height && (e.top = this._frameBounds.top + this._frameBounds.height - this._imageBounds.height + 1),
                e.left + this._imageBounds.width < this._frameBounds.left + this._frameBounds.width && (e.left = this._frameBounds.left + this._frameBounds.width - this._imageBounds.width + 1);
            },
            setImage: function(e)
            {
                this._showSpinner();
                var t = this.$img = $("<img>", {
                    src: e
                });
                this.$bg.empty().append(t),
                this.initImage();
            },
            _fitImage: function()
            {
                var e;
                e = this._imageBounds.ratio >= this._frameBounds.ratio ? this._frameBounds.width / this._imageBounds.nativeWidth : this._frameBounds.height / this._imageBounds.nativeHeight,
                this._scaleImage(e);
            },
            _centerImage: function()
            {
                var e = this.$holder.height(),
                    t = this.$holder.width();
                this.$bg.css({
                    top: e / 2 - this.$bg.height() / 2 + 1,
                    left: t / 2 - this.$bg.width() / 2 + 1
                });
            },
            _scaleImage: function(e)
            {
                var t = this._imageBounds.width = this._imageBounds.nativeWidth * e,
                    n = this._imageBounds.height = this._imageBounds.nativeHeight * e;
                this.$img.css({
                    width: t,
                    height: n
                });
            },
            _showSpinner: function()
            {
                this.$spinner.show();
            },
            _hideSpinner: function()
            {
                this.$spinner.hide();
            },
            getCropData: function()
            {
                var e = {
                    x: -1 * (parseInt(this.$bg.css("left"), 10) - this._frameBounds.left),
                    y: -1 * (parseInt(this.$bg.css("top"), 10) - this._frameBounds.top)
                },
                    t = this.$img.width() / this._imageBounds.nativeWidth,
                    n = {
                        crop_x: e.x,
                        crop_y: e.y,
                        nativeHeight: this._imageBounds.nativeHeight,
                        nativeWidth: this._imageBounds.nativeWidth,
                        height: this.options.size.height,
                        width: this.options.size.width,
                        scale: t
                    };
                return n;
            }
        });
    }),
P.Module.define("ui.ImageUploader", [],
    function()
    {
        return P.Module.extend({
            events: {},
            initialize: function()
            {
                _.bindAll(this, "onUploaderSubmit", "onUploaderComplete", "onUploaderProgress", "onUploaderError");
            },
            onContentReady: function()
            {
                this.ensureUploader();
            },
            getUploadUrl: function()
            {
                return P.absolutify("/upload-image/");
            },
            getFileNameElement: function()
            {
                return this.$fileName || (this.$fileName = this.$(".uploaderProgress").find("span")),
                this.$fileName;
            },
            getButton: function()
            {
                return this.getChildById("upload");
            },
            ensureUploader: function()
            {
                return this.uploader ? this.uploader : (this.uploader = new qq.FineUploaderBasic({
                    debug: P.DEBUG,
                    button: this.getButton().getElement().get(0),
                    multiple: !1,
                    request: {
                        endpoint: this.getUploadUrl(),
                        inputName: "img",
                        forceMultipart: !0,
                        customHeaders: {
                            "X-CSRFToken": P.getCSRFToken()
                        }
                    },
                    callbacks: {
                        onUpload: this.onUploaderSubmit,
                        onComplete: this.onUploaderComplete,
                        onProgress: this.onUploaderProgress,
                        onError: this.onUploaderError,
                        showAlert: function(e)
                        {
                            P.log(e);
                        }
                    }
                }), this.uploader);
            },
            onUploaderSubmit: function()
            {
                this.getButton().showLoading(),
                this.triggerEvent(P.CONST.EVENT_UPLOAD_START),
                P.log("UploaderSubmit", arguments);
            },
            onUploaderComplete: function(e, t, n)
            {
                n.success && (this.getButton().hideLoading(), this.getButton().setStyles({
                    primary: !1
                }), this.triggerEvent(P.CONST.EVENT_UPLOAD_SUCCESS, n, !0), this.getFileNameElement().text(n.filename), P.log("UploaderComplete", arguments));
            },
            onUploaderProgress: function(e, t, n, i)
            {
                var o = Math.round(100 * (n / i));
                this.triggerEvent(P.CONST.EVENT_UPLOAD_PROGRESS, {
                    loaded: n,
                    total: i,
                    percent: o
                }),
                this.getFileNameElement().text(o + "%"),
                P.log("UploaderProgress", arguments);
            },
            resetFileNameElement: function()
            {
                this.getFileNameElement().text(this.extraData.placeholder);
            },
            onUploaderError: function(e, t, n)
            {
                this.getButton().hideLoading(),
                this.triggerEvent(P.CONST.EVENT_UPLOAD_ERROR, n),
                P.log("UploaderError", arguments),
                this.resetFileNameElement();
            }
        });
    }),
P.Module.define("ui.PinPreview", [],
    function()
    {
        return P.Module.extend({
            events: {},
            setImage: function(e)
            {
                var t = this;
                this.showLoading(!0);
                var n = function()
                {
                    t.hideLoading();
                },
                    i = this.$("img").get(0);
                i && (i.onerror = i.onload = n, i.src = e);
            }
        });
    }),
P.Module.define("ui.Progress", [],
    function()
    {
        var e = "active",
            t = P.Module.extend({
                moveStep: function(e)
                {
                    this.setStep(this.options.current_step + e);
                },
                setStep: function(e)
                {
                    e < 0 || e > this.options.steps || (this.options.current_step = e, this._localRender(), e === this.options.steps && this.triggerEvent(P.CONST.EVENT_PROGRESS_COMPLETED, null, !0));
                },
                _localRender: function()
                {
                    var t = this.$el.children("li"),
                        n = this.options.current_step;
                    $.each(t,
                        function(t, i)
                        {
                            $(i).toggleClass(e, n >= t + 1);
                        });
                }
            });
        return t;
    }),
P.Module.define("ui.SearchForm", [],
    function()
    {
        return P.Module.extend({
            events: {
                "submit > form": "onSubmit"
            },
            onChildItemSelected: function(e)
            {
                var t = e.data.item,
                    n = t.get("url");
                n && (this.navigate(n), this.typeaheadField.blur());
                var i = t.get("query") || "";
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_SEARCH_QUERY_UPDATED, i);
            },
            onContentReady: function()
            {
                var e = {};
                e[P.CONST.PUBSUB_TOPIC_SEARCH_QUERY_UPDATED] = this.onSearchQueryUpdated,
                e[P.CONST.PUBSUB_TOPIC_SEARCH_SCOPE_UPDATED] = this.onSearchScopeUpdated,
                this.pubsubSubscribe(P.CONST.PUBSUB_CHANNEL_SITE, e),
                this.typeaheadField = this.getChildById("searchField"),
                this.selectedListener = this.childListen(P.CONST.EVENT_ITEM_SELECTED, this.onChildItemSelected);
            },
            onSearchQueryUpdated: function(e, t, n)
            {
                var i = n || "";
                this.typeaheadField.setValue(i);
            },
            onSearchScopeUpdated: function(e, t, n)
            {
                var i = n || "pins";
                this.currentScope = i,
                this.typeaheadField.setAutocompleteScope(i);
            },
            onSubmit: function()
            {
                var e = this.typeaheadField.getValue(),
                    t = encodeURIComponent(e),
                    n = this.currentScope || this.options.scope || "pins";
                return this.typeaheadField.setAutocompleteScope(n),
                this.navigate("/search/" + n + "/?q=" + t),
                P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_SEARCH_QUERY_UPDATED, e),
                this.typeaheadField.blur(),
                !1;
            }
        });
    }),
P.Module.define("ui.Select", [],
    function()
    {
        return P.Module.extend({});
    }),
P.Module.define("ui.TextField", [],
    function()
    {
        var e = "active",
            t = "has-value",
            n = "<li data-value='${name}'><img src='${img}' /> ${name} <span>(${fullName})</span></li>";
        return P.Module.extend({
            events: {
                click: "onFocus",
                "focus .content": "onContentFocus",
                "blur .content": "onContentBlur"
            },
            onContentReady: function()
            {
                this.options.mentions && this.initAtMentions(),
                this.getContent().placeholder();
            },
            initAtMentions: function()
            {
                this.typeahead = new P.TypeaheadProvider({
                    tags: "mentions",
                    pin_id: this.options.pin_id
                }),
                this.getContent().atwho("@", {
                    data: "/",
                    tpl: n,
                    callbacks: {
                        remote_filter: _.bind(this.onAtMentionFilter, this)
                    }
                }),
                this.atwho = this.getContent().data("atwho");
            },
            onAtMentionFilter: function(e, t, n)
            {
                if (e.q)
                {
                    var i = this;
                    this.typeahead.search(e.q,
                        function(e)
                        {
                            var t = _.map(e.items,
                                function(e)
                                {
                                    return {
                                        name: P.stripTags(e.username),
                                        fullName: P.stripTags(e.label),
                                        img: e.image
                                    };
                                });
                            n(t),
                            i.atwho.settings["@"].data = "/";
                        });
                }
            },
            getContent: function()
            {
                return this.$content || (this.$content = this.$(".content")),
                this.$content;
            },
            getValue: function()
            {
                return P.log("value:", $.trim(this.getContent().val()), this.getContent()),
                $.trim(this.getContent().val());
            },
            onFocus: function()
            {
                this.getContent().focus();
            },
            onContentFocus: function()
            {
                this.$el.addClass(e),
                this.triggerEvent("focus", null, !0);
            },
            onContentBlur: function()
            {
                this.getValue().length ? this.$el.addClass(t) : this.$el.removeClass(t),
                this.$el.removeClass(e);
            }
        });
    }),
P.Module.define("ui.Typeahead", [],
    function()
    {
        var e = "highlighted",
            t = "cid",
            n = "highlighted",
            i = '<a><% if (image) { %><span class="img"><img src="<%- image %>"></span><% } %><% if (tag == "recent_queries") { %><button data-query="<%- query %>" class="remove">Remove</button><% } %><span class="name"><%- label %></span></a>',
            o = '<a><% if (send_pin_image) { %><span class="img"><img src="<%- send_pin_image %>" alt=""></span><% } %><p class="name"><%- label %></p><div class="titleWrapper"><i class="titleIcon<% if (is_pinner) { %> isPinner<% } %>"></i><p class="title"><% if (is_pinner) { %>' + P.string("fellowPinner") + "<% } else if (email) { %>" + "<%- email %>" + "<% } else { %>" + P.string("pickEmailAddress") + "<% } %>" + "</p>" + "</div>" + "</a>",
            s = {
                search: i,
                sendPin: o
            },
            r = Backbone.View.extend({
                tagName: "li",
                initialize: function()
                {
                    var e = this.options.template;
                    this.template = _.template(e),
                    this.model.bind("change", this.render, this);
                },
                render: function()
                {
                    return this.$el.html(this.template(this.model.toJSON())).toggleClass(e, !!this.model.get(n)).data(t, this.model.cid),
                    this;
                }
            });
        return P.Module.extend({
            events: {
                onchange: "onChange",
                "click .results .remove": "onRemoveResult",
                "click .results li": "onResultClick",
                mousedown: "onMousedown",
                "mouseenter .results li": "onResultMouseenter",
                mouseleave: "onMouseleave"
            },
            _isOpen: !1,
            items: [],
            initialize: function()
            {
                this.typeahead = new P.TypeaheadProvider(this.options.options),
                this.listen(this.typeahead, P.CONST.EVENT_DATA, this.onTypeaheadData);
            },
            _triggerNoResultsReturned: function()
            {
                this.triggerEvent(P.CONST.EVENT_TYPEAHEAD_NO_RESULTS_RETURNED, null, !0);
            },
            _triggerResultsReturned: function(e)
            {
                this.triggerEvent(P.CONST.EVENT_TYPEAHEAD_RESULTS_RETURNED, {
                        count: e
                    },
                    !0);
            },
            getItemCount: function()
            {
                return this.itemsToRender.count;
            },
            onTypeaheadData: function(e)
            {
                this.items = e.items,
                this.itemsToRender = _.map(this.items,
                    function(e)
                    {
                        return e.tag = e.tag || "",
                        new Backbone.Model(e);
                    }),
                this.renderResults(),
                0 === this.items.length ? (this.hide(), this._triggerNoResultsReturned()) : this._triggerResultsReturned(this.items.length);
            },
            onContentReady: function()
            {
                this.$results = this.$(".results");
            },
            onMousedown: function()
            {
                this.triggerEvent("mousedown");
            },
            onRemoveResult: function(e)
            {
                e.stopPropagation(),
                e.preventDefault();
                var t = $(e.currentTarget),
                    n = t.attr("data-query");
                if (n)
                {
                    var i = new P.Resource("TypeaheadClearRecentResource", {
                        query: n
                    });
                    i.call("delete"),
                    t.parents("li").remove(),
                    this.items = _.reject(this.items,
                        function(e)
                        {
                            return e.query === n;
                        }),
                    0 === this.items.length && this.hide();
                }
            },
            onResultClick: function(e)
            {
                this.selectElement($(e.currentTarget));
            },
            onResultMouseenter: function(e)
            {
                this.highlightElement($(e.currentTarget));
            },
            onMouseleave: function()
            {
                this.isOpen() && this.highlightElement();
            },
            search: function(e)
            {
                this.lastTerm = e,
                this.typeahead.search(e);
            },
            setAutocompleteScope: function(e)
            {
                this.typeahead.setAutocompleteScope(e);
            },
            renderResults: function()
            {
                var e = this,
                    t = _.map(this.itemsToRender,
                        function(t)
                        {
                            return e.renderItem(t);
                        });
                this.$results.empty().append(t),
                this.show();
            },
            renderItem: function(e)
            {
                var t = this.options.template ? s[this.options.template] : s.search,
                    n = new r({
                        model: e,
                        template: t
                    });
                return n.render().$el;
            },
            hide: function()
            {
                this._isOpen = !1,
                this.highlight(null),
                this.$el.hide();
            },
            show: function()
            {
                this._isOpen = !0,
                this.$el.show();
            },
            isOpen: function()
            {
                return this._isOpen;
            },
            getLastTerm: function()
            {
                return this.lastTerm;
            },
            selectElement: function(e)
            {
                var t = this.getItemByElement(e);
                return this.select(t);
            },
            select: function(e)
            {
                return e = e || this.highlightedItem,
                e && this.triggerEvent(P.CONST.EVENT_ITEM_SELECTED, {
                        item: e
                    },
                    !0),
                e;
            },
            highlightUp: function()
            {
                var e = this.highlightedItem,
                    t = this.itemsToRender,
                    n = e ? _.indexOf(t, e) - 1 : t.length - 1;
                return this.highlight(t[n]);
            },
            highlightDown: function()
            {
                var e = this.highlightedItem,
                    t = this.itemsToRender,
                    n = e ? _.indexOf(t, e) + 1 : 0;
                return this.highlight(t[n]);
            },
            highlightElement: function(e)
            {
                var t = null;
                return e && e[0] && (t = this.getItemByElement(e)),
                this.highlight(t);
            },
            highlight: function(e)
            {
                return e = e || null,
                e === this.highlightedItem ? e : (this.highlightedItem && this.highlightedItem.set(n, !1), e && e.set(n, !0), this.highlightedItem = e, this.triggerEvent(P.CONST.EVENT_ITEM_HIGHLIGHTED, {
                        item: e
                    },
                    !0), e);
            },
            getItemByElement: function(e)
            {
                var n = e.data(t);
                return _.find(this.itemsToRender,
                    function(e)
                    {
                        return e.cid === n;
                    });
            },
            abortSearch: function()
            {
                this.typeahead.abortSearch();
            },
            prefetch: function()
            {
                this.typeahead.prefetch();
            }
        });
    }),
P.Module.define("ui.TypeaheadField", [],
    function()
    {
        return P.Module.extend({
            events: {
                "input .field": "onFieldInput",
                "blur .field": "onFieldBlur",
                "focus .field": "onFieldFocus",
                "keydown .field": "onFieldKeydown"
            },
            initTypeahead: function()
            {
                this.typeahead = this.getChildById("typeahead"),
                this.childListen(P.CONST.EVENT_ITEM_SELECTED, this.onChildItemSelected),
                this.childListen(P.CONST.EVENT_ITEM_HIGHLIGHTED, this.onChildItemHighlighted),
                this.listen(this.typeahead, "mousedown", this.onTypeaheadMousedown);
            },
            hideTypeaheadUnlessPreserved: function()
            {
                this.options.preserve_typeahead || this.typeahead.hide();
            },
            onChildItemSelected: function(e)
            {
                var t = e.data.item,
                    n = t.get("label");
                n && this.setValue(n),
                this.hideTypeaheadUnlessPreserved();
            },
            onChildItemHighlighted: function(e)
            {
                var t = e.data.item,
                    n = t ? t.get("label") : this.typeahead.getLastTerm();
                this.options.populate_on_result_highlight && this.setValue(n);
            },
            onContentReady: function()
            {
                this.initTypeahead(),
                this.$field = this.$(".field"),
                this.$field.placeholder();
            },
            onFieldInput: function()
            {
                this.search();
            },
            onFieldKeydown: function(e)
            {
                var t = this.typeahead,
                    n = P.keyCode;
                if (t.isOpen())
                {
                    switch (e.keyCode)
                    {
                        case n.UP:
                            t.highlightUp(),
                            e.preventDefault();
                            break;
                        case n.DOWN:
                            t.highlightDown(),
                            e.preventDefault();
                            break;
                        case n.ENTER:
                        case n.NUMPAD_ENTER:
                        case n.TAB:
                            var i = t.select();
                            i ? (this.abortSearch(), e.preventDefault()) : this.closeTypeahead();
                            break;
                        case n.ESCAPE:
                            this.closeTypeahead(),
                            e.preventDefault();
                            break;
                        default:
                            this.search();
                    }
                }
                else
                {
                    switch (e.keyCode)
                    {
                        case n.ENTER:
                        case n.NUMPAD_ENTER:
                            this.abortSearch(),
                            this.triggerEvent("enterPressed", {},
                                !0);
                            break;
                        default:
                            this.search();
                    }
                }
            },
            closeTypeahead: function()
            {
                this.abortSearch(),
                this.typeahead.hide();
            },
            onFieldBlur: function()
            {
                return this.cancelBlur ? (this.cancelBlur = !1, void 0) : (this.hideTypeaheadUnlessPreserved(), void 0);
            },
            onFieldFocus: function()
            {
                this.options.search_on_focus && this.search(),
                this.options.prefetch_on_focus && this.typeahead.prefetch();
            },
            onTypeaheadMousedown: function()
            {
                this.cancelBlur = !0,
                window.setTimeout(function()
                {
                    this.cancelBlur = !1;
                },
                    300);
            },
            getValue: function()
            {
                return this.$field.val();
            },
            getField: function()
            {
                return this.$field;
            },
            setValue: function(e)
            {
                this.$field.val(e);
            },
            getTypeaheadResultCount: function()
            {
                return this.typeahead.getItemCount();
            },
            setAutocompleteScope: function(e)
            {
                this.typeahead.setAutocompleteScope(e);
            },
            clear: function()
            {
                this.setValue("");
            },
            abortSearch: function()
            {
                this.searchTimer && window.clearTimeout(this.searchTimer),
                this.typeahead.abortSearch();
            },
            search: function()
            {
                var e = this;
                this.searchTimer && window.clearTimeout(this.searchTimer);
                var t = function()
                {
                    e.typeahead.search(e.getValue());
                },
                    n = this.options.search_delay;
                n ? this.searchTimer = window.setTimeout(t, n) : t();
            },
            blur: function()
            {
                this.$field.blur();
            }
        });
    });
(function()
{
    window.P || (window.P = {
        e: {}
    }),
    P.NOOP = function()
    {
    },
    P.state = {},
    P.Mixins = {},
    P.app = null,
    P.getCSRFToken = function()
    {
        return Cookie.get("csrftoken");
    },
    $("html").ajaxSend(function(e, t)
    {
        t.setRequestHeader("X-CSRFToken", P.getCSRFToken()),
        t.setRequestHeader("X-NEW-APP", "1");
    }),
    P.start = function(e)
    {
        P.Viewport.init(),
        P.Loader.require([e.name],
            function(t)
            {
                P.app = new t({
                    parent: null,
                    el: $("#" + e.uid),
                    children: e.children,
                    options: e.options,
                    resource: e.resource,
                    deps: e.deps,
                    data: e.data,
                    error: e.error
                });
            });
    };
})(),
function()
{
    P.CONST = {
        SUBDOMAIN_PREFIXES: {
            developers: "/developer"
        },
        NOTIFICATIONS_POLL: 45e3,
        UPDATES_MIN_POLL: 45e3,
        UPDATES_MAX_POLL: 9e5,
        BOARD_PRIVACY_SECRET: "secret",
        MAX_SECRET_BOARDS: 3,
        CLASS_DROPDOWN_BUTTON_ACTIVE: "active",
        COOKIE_FB_AUTO_LOGIN_DISABLED: "fba",
        COOKIE_LOCAL_STORAGE: "ls",
        COOKIE_SESSION_STORAGE: "ss",
        COOKIE_SHOW_WELCOME: "d_welcome",
        COOKIE_USE_DENZEL: "_in_d",
        COOKIE_NAG_LANGUAGE: "nl",
        SESSION_FACEBOOK_ID: "_fbid",
        SESSION_FACEBOOK_TOKEN: "_fbt",
        SESSION_KEY_INVITE_FOLLOW: "d_pif_invite",
        EVENT_BOARD_SELECTED: "boardSelected",
        EVENT_BODY_COLUMN_CHANGE: "bodyColumnChange",
        EVENT_BUTTON_CLICK: "buttonClick",
        EVENT_CHANGE: "change",
        EVENT_CLOSE: "close",
        EVENT_CONFIRM: "confirm",
        EVENT_CONTENT_CHANGED: "contentChanged",
        EVENT_DATA: "data",
        EVENT_DATEPICKER_DATE_SELECTED: "datePickerDateSelected",
        EVENT_DATEPICKER_RANGE_SELECTED: "datePickerRangeSelected",
        EVENT_DESTROYED: "destroyed",
        EVENT_DIMS_CHANGED: "dimsChanged",
        EVENT_DISMISS: "dismiss",
        EVENT_DROPDOWN_HIDE: "dropdownHide",
        EVENT_DROPDOWN_SHOW: "dropdownShow",
        EVENT_ERROR: "error",
        EVENT_ERROR_RESOLVED: "errorResolved",
        EVENT_EXTERNAL_CLICK: "externalLinkClicked",
        EVENT_BOARD_FOLLOW: "boardFollowed",
        EVENT_BOARD_UNFOLLOW: "boardUnfollowed",
        EVENT_FAST_FOLLOW_CATEGORY_SELECTED: "followpageCategorySelected",
        EVENT_HOVERINTENT_ENTER_COMPLETE: "mouseEnterComplete",
        EVENT_HOVERINTENT_ENTER_START: "mouseEnterStart",
        EVENT_HOVERINTENT_OUT_COMPLETE: "mouseOutComplete",
        EVENT_HOVERINTENT_OUT_START: "mouseOutStart",
        EVENT_INCREMENT_BUTTON_CREATE: "incrementButtonCreate",
        EVENT_INCREMENT_BUTTON_DESTROY: "incrementButtonDestroy",
        EVENT_INVITE_EMAIL: "inviteEmail",
        EVENT_INVITE_USER: "inviteUser",
        EVENT_ITEM_HIGHLIGHTED: "itemHighlighted",
        EVENT_ITEM_SELECTED: "itemSelected",
        EVENT_ITEMS_END: "itemsEnd",
        EVENT_ITEMS_REQUEST_START: "itemsRequestStart",
        EVENT_ITEMS_REQUEST_SUCCESS: "itemsRequestSuccess",
        EVENT_LAZY_IMAGE_COMPLETE: "lazyImageComplete",
        EVENT_NAVIGATE: "navigate",
        EVENT_NEXT: "next",
        EVENT_OPEN: "open",
        EVENT_PIN_CREATE: "pinCreate",
        EVENT_PIN_CREATE_OPENED: "pinCreateOpened",
        EVENT_PIN_LIKED: "pinLiked",
        EVENT_PIN_UNLIKED: "pinUnliked",
        EVENT_PIN_UPDATED: "pinUpdated",
        EVENT_PREVIOUS: "previous",
        EVENT_PROGRESS_COMPLETED: "progressCompleted",
        EVENT_RESIZE: "resize",
        EVENT_STICKY_FIXED: "stickyUpdate",
        EVENT_SUBMIT_VALIDATED: "submitValidated",
        EVENT_TYPEAHEAD_NO_RESULTS_RETURNED: "typeaheadNoResultsReturned",
        EVENT_TYPEAHEAD_RESULTS_RETURNED: "typeaheadResultsReturned",
        EVENT_UPLOAD_SUCCESS: "uploadSuccess",
        EVENT_UPLOAD_START: "uploadStart",
        EVENT_UPLOAD_ERROR: "uploadError",
        EVENT_UPLOAD_PROGRESS: "uploadProgress",
        EVENT_USER_CLICK: "userClick",
        EVENT_USER_FOLLOW: "userFollow",
        GA_ACTION_CLICK: "click",
        GA_ACTION_CLICK_CANCEL: "click_cancel",
        GA_ACTION_CLICK_CLOSE: "click_close",
        GA_ACTION_CLICK_CONFIRM: "click_confirm",
        GA_ACTION_CLICK_SUBMIT: "click_submit",
        GA_ACTION_ENTER_SUBMIT: "enter_submit",
        GA_ACTION_ERROR: "error",
        GA_ACTION_OPEN_MODAL: "open_modal",
        GA_ACTION_SELECT_SUBMIT: "select_submit",
        GA_ACTION_SUCCESS: "success",
        PUBSUB_CHANNEL_ANALYTICS: "analytics",
        PUBSUB_CHANNEL_CURRENT_USER: "currentUser",
        PUBSUB_CHANNEL_MAIN_MODULE: "mainModule",
        PUBSUB_CHANNEL_SITE: "site",
        PUBSUB_CHANNEL_TUTORIAL: "tutorial",
        PUBSUB_MESSAGE_BOARD_SET_PUBLIC: "boardSetPublic",
        PUBSUB_MESSAGE_USER_EMAIL_UPDATED: "userEmailUpdated",
        PUBSUB_TOPIC_APP_VERSION: "appVersion",
        PUBSUB_TOPIC_BOARD_APPROVED_COLLABORATOR_INVITE: "boardApprovedCollaboratorInvite",
        PUBSUB_TOPIC_BOARD_COVER_UPDATED: "boardCoverUpdated",
        PUBSUB_TOPIC_BOARD_CREATED: "boardCreated",
        PUBSUB_TOPIC_BOARD_DELETED: "boardDeleted",
        PUBSUB_TOPIC_BOARD_FOLLOW: "boardFollow",
        PUBSUB_TOPIC_BOARD_REMOVED_COLLABORATOR_SELF: "boardRemovedCollaboratorSelf",
        PUBSUB_TOPIC_BOARD_UNFOLLOW: "boardUnfollow",
        PUBSUB_TOPIC_BOARD_UPDATED: "boardUpdated",
        PUBSUB_TOPIC_BOARD_WRITE_ACCESS_UPDATED: "boardWriteAccessUpdated",
        PUBSUB_TOPIC_CONSUMER_UPDATED: "consumerUpdated",
        PUBSUB_TOPIC_CONSUMER_LIST_UPDATED: "consumerListUpdated",
        PUBSUB_TOPIC_CURRENT_CATEGORY: "currentCategory",
        PUBSUB_TOPIC_MAIN_MODULE_NEW: "mainModuleNew",
        PUBSUB_TOPIC_PAGE_INFO: "pageInfo",
        PUBSUB_TOPIC_PIN_COMMENT_CREATED: "pinCommentCreated",
        PUBSUB_TOPIC_PIN_CREATED: "pinCreated",
        PUBSUB_TOPIC_PIN_DELETED: "pinDeleted",
        PUBSUB_TOPIC_PIN_LIKED: "pinLiked",
        PUBSUB_TOPIC_PIN_UNLIKED: "pinUnliked",
        PUBSUB_TOPIC_PIN_UPDATED: "pinUpdated",
        PUBSUB_TOPIC_SEARCH_QUERY_UPDATED: "searchQueryUpdated",
        PUBSUB_TOPIC_SEARCH_SCOPE_UPDATED: "searchScopeUpdated",
        PUBSUB_TOPIC_TIMING_METRICS_EMITTED: "timingMetricsEmitted",
        PUBSUB_TOPIC_TIMING_TRACE_EMITTED: "timingTraceEmitted",
        PUBSUB_TOPIC_TUTORIAL_CATEGORIES: "categories",
        PUBSUB_TOPIC_USER_BLOCKED: "userBlocked",
        PUBSUB_TOPIC_USER_FOLLOW: "userFollow",
        PUBSUB_TOPIC_USER_UNBLOCKED: "userUnblocked",
        PUBSUB_TOPIC_USER_UNFOLLOW: "userUnfollow",
        PUBSUB_TOPIC_USER_UPDATED: "userUpdated",
        STOPWATCH_SET_AS_MAIN_MODULE_SUCCESS: "setAsMainModule success",
        MAX_CHARS_FOR_BOARD_TITLE: 100,
        MAX_CHARS_FOR_USER_DESCRIPTION: 160,
        MAX_CHARS_FOR_BOARD_PIN_DESCRIPTION: 500,
        OVERFLOWING_TEXT_OVERFLOWING_CLASS: "overflowing",
        MIN_PINNABLE_IMAGE_HEIGHT: 50,
        MIN_PINNABLE_IMAGE_WIDTH: 100,
        ErrorStrategy: {
            SHOW: 0,
            BUBBLE: 1,
            REMOVE: 2
        },
        PositionMode: {
            VIEWPORT_MIDDLE: 1,
            ANCHORED: 2
        }
    };
    var e, t, n = parseInt("0000000000001", 2),
        i = 0;
    P.CONST.PositionPointFlag = {},
    _.each(["VERTICAL", "HORIZONTAL"],
        function(o)
        {
            t = 0,
            _.each(["BOTTOM", "LEFT", "CENTER", "RIGHT", "TOP"],
                function(s)
                {
                    e = n << i++,
                    t |= e,
                    P.CONST.PositionPointFlag["FLAG_" + o + "_" + s] = e;
                }),
            P.CONST.PositionPointFlag["FLAG_" + o] = t;
        });
    var o = P.CONST.PositionPointFlag;
    P.CONST.PositionPoint = {
        BOTTOM_CENTER: o.FLAG_VERTICAL_BOTTOM | o.FLAG_VERTICAL_CENTER,
        BOTTOM_LEFT: o.FLAG_VERTICAL_BOTTOM | o.FLAG_VERTICAL_LEFT,
        BOTTOM_RIGHT: o.FLAG_VERTICAL_BOTTOM | o.FLAG_VERTICAL_RIGHT,
        TOP_CENTER: o.FLAG_VERTICAL_TOP | o.FLAG_VERTICAL_CENTER,
        TOP_LEFT: o.FLAG_VERTICAL_TOP | o.FLAG_VERTICAL_LEFT,
        TOP_RIGHT: o.FLAG_VERTICAL_TOP | o.FLAG_VERTICAL_RIGHT,
        LEFT_BOTTOM: o.FLAG_HORIZONTAL_LEFT | o.FLAG_HORIZONTAL_BOTTOM,
        LEFT_CENTER: o.FLAG_HORIZONTAL_LEFT | o.FLAG_HORIZONTAL_CENTER,
        LEFT_TOP: o.FLAG_HORIZONTAL_LEFT | o.FLAG_HORIZONTAL_TOP,
        RIGHT_BOTTOM: o.FLAG_HORIZONTAL_RIGHT | o.FLAG_HORIZONTAL_BOTTOM,
        RIGHT_CENTER: o.FLAG_HORIZONTAL_RIGHT | o.FLAG_HORIZONTAL_CENTER,
        RIGHT_TOP: o.FLAG_HORIZONTAL_RIGHT | o.FLAG_HORIZONTAL_TOP
    };
}(),
function()
{
    var e = P.NOOP;
    _.extend(e.prototype, {
        length: function()
        {
            var e = Cookie.get(P.CONST.COOKIE_SESSION_STORAGE),
                t = e ? JSON.parse(e) : {};
            return _.keys(t).length;
        },
        key: function()
        {
            P.log("ERROR", "intentionally unimplemented function");
        },
        getItem: function(e)
        {
            var t = Cookie.get(P.CONST.COOKIE_SESSION_STORAGE),
                n = t ? JSON.parse(t) : {};
            return n[e];
        },
        setItem: function(e, t)
        {
            var n = Cookie.get(P.CONST.COOKIE_SESSION_STORAGE),
                i = n ? JSON.parse(n) : {};
            i[e] = t,
            Cookie.set(P.CONST.COOKIE_SESSION_STORAGE, JSON.stringify(i));
        },
        removeItem: function(e)
        {
            var t = Cookie.get(P.CONST.COOKIE_SESSION_STORAGE),
                n = t ? JSON.parse(t) : {};
            delete n[e],
            Cookie.set(P.CONST.COOKIE_SESSION_STORAGE, JSON.stringify(n));
        },
        clear: function()
        {
            Cookie.unset(P.CONST.COOKIE_SESSION_STORAGE);
        }
    });
    var t = P.NOOP;
    _.extend(t.prototype, {
        length: function()
        {
            return window.sessionStorage.length;
        },
        key: function()
        {
            P.log("ERROR", "intentionally unimplemented function");
        },
        getItem: function(e)
        {
            return JSON.parse(window.sessionStorage.getItem(e));
        },
        setItem: function(e, t)
        {
            window.sessionStorage.setItem(e, JSON.stringify(t));
        },
        removeItem: function(e)
        {
            window.sessionStorage.removeItem(e);
        },
        clear: function()
        {
            window.sessionStorage.clear();
        }
    });
    var n = P.NOOP;
    _.extend(n.prototype, {
        length: function()
        {
            return window.localStorage.length;
        },
        key: function()
        {
            P.log("ERROR", "intentionally unimplemented function");
        },
        getItem: function(e)
        {
            return JSON.parse(window.localStorage.getItem(e));
        },
        setItem: function(e, t)
        {
            window.localStorage.setItem(e, JSON.stringify(t));
        },
        removeItem: function(e)
        {
            window.localStorage.removeItem(e);
        },
        clear: function()
        {
            window.localStorage.clear();
        }
    });
    var i = function(i)
    {
        var o = i ? window.sessionStorage : window.localStorage,
            s = i ? P.CONST.COOKIE_SESSION_STORAGE : P.CONST.COOKIE_LOCAL_STORAGE,
            r = !1,
            a = o;
        if (a)
        {
            try
            {
                a.setItem("testing", "test"),
                a.removeItem("testing");
            }
            catch(l)
            {
                if (l.code !== window.DOMException.QUOTA_EXCEEDED_ERR || 0 !== a.length)
                {
                    throw l;
                }
                r = !0;
            }
        }
        else
        {
            r = !0;
        }
        return r ? new e(s) : i ? new t : new n;
    };
    P.SessionStorage = i(!0),
    P.LocalStorage = i(!1),
    window.P_TEST_MODE && (P.CookieBackedStorage = e, P.WindowSessionStorage = t, P.WindowLocalStorage = n, P.FakeStorage = function()
    {
        this.len = 0,
        this.storage = {};
    },
    _.extend(P.FakeStorage.prototype, {
        length: function()
        {
            return this.length;
        },
        key: function()
        {
            P.log("ERROR", "intentionally unimplemented function");
        },
        getItem: function(e)
        {
            return this.storage[e];
        },
        setItem: function(e, t)
        {
            this.storage[e] = t;
        },
        removeItem: function(e)
        {
            delete this.storage[e];
        },
        clear: function()
        {
            this.storage.key = {};
        }
    }));
}(),
function()
{
    P.Logger = function(e)
    {
        this.name = e;
        var t;
        if (P.DEBUG)
        {
            var n = P.LocalStorage.getItem(this._getStorageKey());
            null !== n && void 0 !== n && (t = parseInt(n, 10));
        }
        void 0 === t && (t = P.DEBUG ? P.Logger.LOG_LEVEL.DEBUG : P.Logger.LOG_LEVEL.NONE),
        this.setLogLevel(t);
    };
    var e = window.navigator.userAgent,
        t = window.navigator.platform,
        n = [],
        i = {};
    _.extend(P.Logger, {
        LOG_LEVEL: {
            DEBUG: 0,
            WARN: 1,
            ERROR: 2,
            NONE: 3
        },
        SERVER_LOG_TYPE: {
            LOG: "log",
            ERROR: "error",
            PAGE_LOAD_METRIC: "page_load_metric",
            APP_METRIC: "app_metric"
        },
        getLogger: function(e)
        {
            var t = i[e];
            return t || (t = new P.Logger(e), n.push(t), i[e] = t),
            t;
        },
        getAll: function()
        {
            return n;
        },
        getByName: function(e)
        {
            return i[e];
        }
    }),
    window.P_TEST_MODE && (P.Logger.clear = function()
    {
        n = [],
        i = {};
    }),
    _.extend(P.Logger.prototype, {
        debug: function()
        {
            var e = _.toArray(arguments);
            this._addLogName(e),
            this._printToConsole(P.Logger.LOG_LEVEL.DEBUG, e);
        },
        warn: function()
        {
            var e = _.toArray(arguments);
            this._addLogName(e),
            this._printToConsole(P.Logger.LOG_LEVEL.WARN, e);
        },
        error: function()
        {
            var e = _.toArray(arguments);
            this._addLogName(e),
            this._printToConsole(P.Logger.LOG_LEVEL.ERROR, e);
            var t = e.shift(),
                n = {
                    message: t,
                    messages: e
                };
            this.logToServer(P.Logger.SERVER_LOG_TYPE.ERROR, "post", n);
        },
        setLogLevel: function(e)
        {
            this.logLevel = e,
            P.DEBUG && P.LocalStorage.setItem(this._getStorageKey(), e);
        },
        _getStorageKey: function()
        {
            return "logLevel." + this.name;
        },
        _addLogName: function(e)
        {
            e[0] = this.name + ": " + e[0];
        },
        _printToConsole: function(e, t)
        {
            var n = window.console || null;
            if (n && !(this.logLevel > e))
            {
                var i;
                e === P.Logger.LOG_LEVEL.ERROR && n.error ? i = n.error : e === P.Logger.LOG_LEVEL.WARN && n.warn ? i = n.warn : n.log && (i = n.log),
                i && Function.prototype.apply.apply(i, [n, t]);
            }
        },
        logToServer: function(n, i, o)
        {
            var s = "/_/_/report/" + n + "/",
                r = {
                    app_version: P.AppVersion.currentVersion,
                    source_url: P.getCurrentUrl(),
                    user_agent: e,
                    platform: t,
                    app_invalid: P.AppVersion.invalid
                };
            P.state.activeTarget && (r.active_target = P.state.activeTarget.getFullName());
            var a = _.extend(r, o),
                l = function()
                {
                    var e = {
                        message: "Failed to log error!",
                        method: i
                    };
                    $.post("/_/_/report/error/", e);
                };
            if ("get" === i)
            {
                var u = {
                    data: JSON.stringify(a)
                };
                $.get(s, u).fail(l);
            }
            else
            {
                $.post(s, JSON.stringify(a)).fail(l);
            }
        }
    });
    var o = P.Logger.getLogger("Default");
    P.log = function()
    {
        var e = _.toArray(arguments),
            t = "DEBUG";
        switch (_.contains(["DEBUG", "WARN", "ERROR"], e[0]) && (t = e.shift()), t)
        {
            case "DEBUG":
                o.debug(e);
                break;
            case "WARN":
                o.warn(e);
                break;
            case "ERROR":
                o.error(e);
        }
    };
}(),
function()
{
    for (var e = 0,
        t = ["ms", "moz", "webkit", "o"], n = 0; n < t.length && !window.requestAnimationFrame; ++n)
    {
        window.requestAnimationFrame = window[t[n] + "RequestAnimationFrame"],
        window.cancelAnimationFrame = window[t[n] + "CancelAnimationFrame"] || window[t[n] + "CancelRequestAnimationFrame"];
    }
    window.requestAnimationFrame || (window.requestAnimationFrame = function(t)
    {
        var n = (new Date).getTime(),
            i = Math.max(0, 16 - (n - e)),
            o = window.setTimeout(function()
            {
                t(n + i);
            },
                i);
        return e = n + i,
        o;
    }),
    window.cancelAnimationFrame || (window.cancelAnimationFrame = function(e)
    {
        clearTimeout(e);
    });
}(),
function()
{
    var e = qq.UploadHandlerForm.prototype._createForm;
    qq.UploadHandlerForm.prototype._createForm = function()
    {
        var t = e.apply(this, arguments),
            n = $('<input type="hidden" name="csrfmiddlewaretoken" value="' + P.getCSRFToken() + '">');
        return t.appendChild(n.get(0)),
        t;
    };
}(),
function()
{
    var e = 0;
    P.PubSub = function(e)
    {
        this.ns = e,
        this.channels = {};
        var t = this;
        this.Subscriber = function(e, i)
        {
            n.call(this, t, e, i);
        },
        this.Subscriber.prototype = n.prototype;
    },
    _.extend(P.PubSub.prototype, {
        subscribe: function(e, t, n, i)
        {
            var o = new this.Subscriber(e, {
                handler: n,
                scope: i
            });
            return o.subscribe(t),
            o;
        },
        publish: function(e, t, n)
        {
            this.getChannel(e).publish(t, n);
        },
        getChannel: function(e)
        {
            return this.channels[e] || (this.channels[e] = new t(this, e)),
            this.channels[e];
        },
        clearChannel: function(e)
        {
            var t = this.channels[e];
            t && (t.unsubscribeAll(), delete this.channels[e]);
        }
    });
    var t = function(e, t)
    {
        this.pubsub = e,
        this.target = t,
        this.subscribers = {},
        this.filters = {},
        this.messages = {};
    };
    _.extend(t.prototype, {
        addSubscriber: function(e, t)
        {
            var n = this,
                i = e.getId();
            return this.subscribers[i] = e,
            _.each(t,
                function(t)
                {
                    n.filters[t] || (n.filters[t] = {}),
                    n.filters[t][i] || (n.filters[t][i] = e, _.isUndefined(n.messages[t]) || e.publish(t, n.messages[t]));
                }),
            e;
        },
        removeSubscriber: function(e, t)
        {
            var n = this,
                i = e.getId();
            _.each(t,
                function(e)
                {
                    n.filters[e] && delete n.filters[e][i];
                }),
            _.keys(this.subscribers).length < 1 && this.pubsub.clearChannel(this.target);
        },
        publish: function(e, t)
        {
            _.each(this.filters[e],
                function(n)
                {
                    n.publish(e, t);
                }),
            "*" !== e && this.publish("*", t),
            this.messages[e] = t;
        },
        getSubscribers: function()
        {
            var e = _.toArray(arguments);
            if (!e.length)
            {
                return _.values(this.subscribers);
            }
            var t = this,
                n = {};
            return _.each(e,
                function(e)
                {
                    _.extend(n, t.filters[e]);
                }),
            _.values(n);
        },
        unsubscribeAll: function()
        {
            _.each(this.subscribers,
                function(e)
                {
                    e.unsubscribe();
                });
        }
    });
    var n = function(e, t, n)
    {
        this.pubsub = e,
        this.target = t,
        this.options = n,
        this.topics = {};
    };
    _.extend(n.prototype, {
        publish: function(e, t)
        {
            return this.getHandler().call(this.getScope(), this.target, e, t),
            this;
        },
        subscribe: function()
        {
            var e = this,
                t = _.toArray(arguments);
            return this.getChannel().addSubscriber(e, t),
            _.each(t,
                function(t)
                {
                    e.topics[t] = 1;
                }),
            this;
        },
        unsubscribe: function()
        {
            var e = this,
                t = _.toArray(arguments);
            return 0 === t.length && (t = this.getTopics()),
            _.each(t,
                function(t)
                {
                    delete e.topics[t];
                }),
            this.getChannel().removeSubscriber(this, t),
            this;
        },
        getChannel: function()
        {
            return this.pubsub.getChannel(this.target);
        },
        getHandler: function()
        {
            return this.options.handler;
        },
        getScope: function()
        {
            return _.result(this.options, "scope");
        },
        getName: function()
        {
            return _.result(this.options, "name");
        },
        getId: function()
        {
            return this.id || (this.id = e++),
            this.id;
        },
        getTopics: function()
        {
            return _.keys(this.topics);
        }
    }),
    P.PubSub.Subscriber = n,
    P.PubSub.Channel = t,
    P.pubsub = new P.PubSub("local");
}(),
function()
{
    P.AppVersion = {
        currentVersion: null,
        invalid: !1,
        setup: function(e)
        {
            var t = this;
            this.currentVersion = e,
            P.pubsub.subscribe(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_APP_VERSION,
                function(e, n, i)
                {
                    t.updateVersion(i);
                });
        },
        updateVersion: function(e)
        {
            e !== this.currentVersion && (this.invalid = !0),
            this.currentVersion = e;
        }
    };
}(),
function()
{
    var e = P.Logger.getLogger("Errors");
    P.Errors = {},
    P.Errors.ENABLE_WRAPPING = P.e.ew,
    P.Errors.wrapFn = function(e, t)
    {
        return t ? P.Errors.ENABLE_WRAPPING ?
            function()
            {
                try
                {
                    return t.apply(this, arguments);
                }
                catch(n)
                {
                    throw n.loggedToServer || (P.Errors.reportError(this, e, arguments, n), n.loggedToServer = !0),
                    n;
                }
            } : t : function()
            {
            };
    },
    P.Errors.wrap = function(e, t)
    {
        _.each(t,
            function(t)
            {
                var n = e[t];
                e[t] = P.Errors.wrapFn(t, n);
            });
    },
    P.Errors.reportError = function(t, n, i, o)
    {
        var s = {
            format: "sentry",
            fn_name: n || "unknown_function_name"
        };
        if (t instanceof P.Module)
        {
            for (var r = n,
                a = t; a;)
            {
                r = a.getDebugInfo() + ":" + r,
                a = a.parent;
            }
            s.error_path = r;
        }
        else
        {
            t instanceof P.Resource && (s.resource_name = t.name, s.options = JSON.stringify(t.options));
        }
        if (i[0] instanceof $.Event)
        {
            var l = i[0],
                u = l.currentTarget;
            s.event = {
                type: l.type,
                target_class: u.className.replace(/\s+/g, " ")
            },
            u.href && (s.event.target_href = u.href);
        }
        s.traceback = printStackTrace({
            e: o
        }).join("\n"),
        e.error(o.message, s);
    },
    P.showError = function(e, t)
    {
        e = _.escape(e);
        var n = {
            name: "ConfirmDialog",
            options: {
                view_type: "error",
                message: e,
                template: null
            }
        };
        P.loadModule(n,
            function(e)
            {
                t && e.on(P.CONST.EVENT_CONFIRM, t),
                P.ModalManager.instance().showInModal(e);
            });
    };
}(),
function()
{
    P.Mixins.PreventScroll = {
        startPreventScroll: function(e, t)
        {
            this.stopPreventScroll(),
            this._preventScrollListener = this.listen(e, "mousewheel",
                function(n)
                {
                    var i = n.originalEvent.wheelDeltaY < 0 ? "down" : "up",
                        o = e.scrollTop();
                    if ("down" === i)
                    {
                        var s = e.height() + o;
                        s >= t.height() && n.preventDefault();
                    }
                    else
                    {
                        0 === o && n.preventDefault();
                    }
                });
        },
        stopPreventScroll: function()
        {
            this._preventScrollListener && (this.removeListener(this._preventScrollListener), this._preventScrollListener = null);
        }
    };
}(),
function()
{
    P.User = Backbone.Model.extend({
        isAuthenticated: function()
        {
            return !!this.get("id");
        },
        attemptLogin: function()
        {
            P.e.fba && this.attemptLoginWithFacebook();
        },
        attemptLoginWithFacebook: function()
        {
            if (!Cookie.get(P.CONST.COOKIE_FB_AUTO_LOGIN_DISABLED))
            {
                var e = this;
                P.FBEnsureInit(function()
                {
                    var t = _.bind(e._attemptLoginWithFacebook, e);
                    P.FB.getLoginStatus(t, !0);
                });
            }
        },
        _attemptLoginWithFacebook: function(e)
        {
            if (e.authResponse)
            {
                var t = {
                    facebook_id: e.authResponse.userID,
                    facebook_token: e.authResponse.accessToken,
                    facebook_autologin: !0
                };
                this.login(t,
                    function()
                    {
                        window.location.reload(!0);
                    });
            }
        },
        login: function(e, t, n, i)
        {
            var o = new P.Resource("UserSessionResource", e);
            o.call("create", {
                success: function(e)
                {
                    P.log("Login, successful", e),
                    P.trackRegisterAction("login"),
                    t && t(e);
                },
                error: n || P.NOOP,
                complete: i || P.NOOP
            });
        },
        logout: function(e)
        {
            Cookie.set(P.CONST.COOKIE_FB_AUTO_LOGIN, 1),
            e();
        }
    }),
    P.currentUser = new P.User;
}(),
function()
{
    var e = {
        SMALL: "Small",
        MEDIUM: "Medium"
    },
        t = {
            size: e.MEDIUM
        },
        n = function(e)
        {
            this.options = _.extend({},
                t, e),
            this.$spinEl = null;
        };
    n.Size = e,
    n.prototype = {
        spin: function(e)
        {
            this.$spinEl && this.stop();
            var t = "spinner" + this.options.size;
            this.$spinEl = $('<div class="Spinner"><div class="' + t + '"></div></div>'),
            this.$spinEl.prependTo(e);
        },
        stop: function()
        {
            this.$spinEl.remove(),
            this.$spinEl = null;
        }
    },
    P.Spinner = n;
}(),
function()
{
    P.string = function(e)
    {
        return P.STRINGS ? P.STRINGS[e] || e : e;
    };
}(),
function()
{
    function e()
    {
    }
    function t()
    {
    }
    function n()
    {
    }
    var i, o = function(e)
    {
        this.name = e,
        this.notes = null,
        this.directChildren = [],
        this.asyncChildren = [],
        this.begin = null,
        this.end = null;
    };
    i = window.performance && window.performance.now ? _.bind(window.performance.now, window.performance) : Date.now ? _.bind(Date.now, Date) : function()
    {
        return +new Date;
    },
    o.prototype = {
        addChild: function(e)
        {
            this.directChildren.push(e);
        },
        addAsync: function(e)
        {
            this.asyncChildren.push(e);
        },
        start: function()
        {
            this.begin = i();
        },
        stop: function()
        {
            this.end = i();
        },
        getWallClockLength: function()
        {
            return this.end - this.begin;
        },
        getSelfLength: function()
        {
            var e = _.reduce(this.directChildren,
                function(e, t)
                {
                    return e + t.getWallClockLength();
                },
                0);
            return this.getWallClockLength() - e;
        },
        _getTreeEnd: function()
        {
            var e = this.end;
            return e = _.reduce(this.directChildren,
                function(e, t)
                {
                    return Math.max(t._getTreeEnd(), e);
                },
                e),
            e = _.reduce(this.asyncChildren,
                function(e, t)
                {
                    return Math.max(t._getTreeEnd(), e);
                },
                e);
        },
        getTreeLength: function()
        {
            return this._getTreeEnd() - this.begin;
        },
        setNote: function(e, t)
        {
            this.notes || (this.notes = {}),
            this.notes[e] = t;
        },
        find: function(e)
        {
            if (e(this))
            {
                return this;
            }
            var t, n;
            for (t = 0; t < this.directChildren.length; t++)
            {
                if (n = this.directChildren[t].find(e))
                {
                    return n;
                }
            }
            for (t = 0; t < this.asyncChildren.length; t++)
            {
                if (n = this.asyncChildren[t].find(e))
                {
                    return n;
                }
            }
        },
        each: function(e)
        {
            this.find(function(t)
            {
                return e(t),
                !1;
            });
        }
    };
    var s = function()
    {
        this.stack = [];
    };
    s.prototype = {
        peek: function()
        {
            return this.stack[this.stack.length - 1];
        },
        setNote: function(e, t)
        {
            this.peek().setNote(e, t);
        },
        start: function(e)
        {
            var t = new o(e),
                n = this.peek();
            n && n.addChild(t),
            this.push(t);
        },
        startContinuation: function(e, t)
        {
            var n = new o(e),
                i = this.peek();
            i ? i.addChild(n) : t.addAsync(n),
            this.push(n);
        },
        push: function(e)
        {
            e.start(),
            this.stack.push(e);
        },
        stop: function()
        {
            var e = this.stack.pop();
            if (e.stop(), 0 === this.stack.length)
            {
                var t = function()
                {
                    P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_ANALYTICS, P.CONST.PUBSUB_TOPIC_TIMING_TRACE_EMITTED, e);
                };
                _.delay(t, 1e4);
            }
        }
    };
    var r = new s;
    e.prototype = {
        wrap: function()
        {
        },
        wrapMethods: function()
        {
        },
        setNote: function()
        {
        },
        wrapContinuation: function()
        {
        }
    },
    t.prototype = {
        wrap: function(e, t)
        {
            return function()
            {
                r.start(e);
                var n = t.apply(this, arguments);
                return r.stop(),
                n;
            };
        },
        wrapMethods: function(e, t, n)
        {
            var i = this;
            _.each(n,
                function(n)
                {
                    var o = e[n];
                    e[n] = i.wrap(t + "." + n, o);
                });
        },
        setNote: function(e, t)
        {
            r.setNote(e, t);
        },
        wrapContinuation: function(e, t)
        {
            var n = r.peek();
            return function()
            {
                r.startContinuation(e, n);
                var i = P.Errors.wrapFn(e, t),
                    o = i.apply(this, arguments);
                return r.stop(),
                o;
            };
        }
    },
    n.prototype = {
        wrap: function(e, t)
        {
            return t;
        },
        wrapMethods: P.NOOP,
        setNote: P.NOOP,
        wrapContinuation: function(e, t)
        {
            return t;
        }
    },
    P.stopwatch = P.e.sw ? new t : new n;
}(),
function()
{
    var e = function(e)
    {
        this.timingTrace = e,
        this.category = null,
        this.subCategory = null,
        this.numResourceCalls = null,
        this.numModuleBuilds = null,
        this.numTimingTraceNodes = null,
        this.mainModuleMs = null,
        this.totalMs = null;
    };
    e.prototype = {
        setCategory: function(e)
        {
            this.category = e;
        },
        setSubCategory: function(e)
        {
            this.subCategory = e;
        },
        setNumResourceCalls: function(e)
        {
            this.numResourceCalls = e;
        },
        setNumModuleBuilds: function(e)
        {
            this.numModuleBuilds = e;
        },
        setNumTimingTraceNodes: function(e)
        {
            this.numTimingTraceNodes = e;
        },
        getCounts: function()
        {
            return {
                numResourceCalls: this.numResourceCalls,
                numModuleBuilds: this.numModuleBuilds,
                numTimingTraceNodes: this.numTimingTraceNodes
            };
        },
        setMainModuleMs: function(e)
        {
            this.mainModuleMs = e;
        },
        setTotalMs: function(e)
        {
            this.totalMs = e;
        },
        getTimes: function()
        {
            return {
                mainModuleMs: this.mainModuleMs,
                totalMs: this.totalMs
            };
        }
    };
    var t = {
        fromTimingTrace: function(t)
        {
            var n = new e(t);
            switch (t.name)
            {
                case "P.navigate":
                case "Router.onStateChange":
                    switch (t.name)
                    {
                        case "P.navigate":
                            n.setCategory("navigate");
                            break;
                        case "Router.onStateChange":
                            n.setCategory("state change");
                    }
                    var i = t.find(function(e)
                    {
                        return "Router.resolve" === e.name;
                    });
                    i && n.setSubCategory(_.values(i.notes).join(","));
                    break;
                case "ShowModalButton.onClick":
                    n.setCategory("open modal"),
                    n.setSubCategory(_.values(t.notes).join(","));
                    break;
                case "PinCreate.createPin":
                    n.setCategory("createPin");
                    break;
                default:
                    return null;
            }
            var o = 0,
                s = 0,
                r = 0;
            t.each(function(e)
            {
                "Resource.call" === e.name ? o++ : "Module._build" === e.name && s++,
                r++;
            }),
            n.setNumResourceCalls(o),
            n.setNumModuleBuilds(s),
            n.setNumTimingTraceNodes(r);
            var a = t.getTreeLength(),
                l = null;
            return t.find(function(e)
            {
                var n = e.name === P.CONST.STOPWATCH_SET_AS_MAIN_MODULE_SUCCESS;
                return n && (l = e.end - t.begin),
                n;
            }),
            n.setMainModuleMs(l || a),
            n.setTotalMs(a),
            n;
        }
    };
    P.pubsub.subscribe(P.CONST.PUBSUB_CHANNEL_ANALYTICS, P.CONST.PUBSUB_TOPIC_TIMING_TRACE_EMITTED,
        function(e, n, i)
        {
            var o = i,
                s = t.fromTimingTrace(o);
            s && P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_ANALYTICS, P.CONST.PUBSUB_TOPIC_TIMING_METRICS_EMITTED, s);
        });
}(),
function()
{
    if (P.e.sw)
    {
        var e = P.Logger.getLogger("ReportMetrics");
        $(window).on("load",
            function()
            {
                var t = {};
                window.performance.getEntriesByType && (t.resourceTimings = window.performance.getEntriesByType("resource")),
                window.performance.navigation && (t.navigation = window.performance.navigation),
                window.performance.timing && (t.timing = window.performance.timing),
                P.PAGE_ROUTE_PATTERN && (t.routePattern = P.PAGE_ROUTE_PATTERN),
                _.isEmpty(t) || e.logToServer(P.Logger.SERVER_LOG_TYPE.PAGE_LOAD_METRIC, "post", t);
            }),
        P.pubsub.subscribe(P.CONST.PUBSUB_CHANNEL_ANALYTICS, P.CONST.PUBSUB_TOPIC_TIMING_METRICS_EMITTED,
            function(t, n, i)
            {
                var o = _.clone(i);
                delete o.timingTrace,
                e.logToServer(P.Logger.SERVER_LOG_TYPE.APP_METRIC, "post", o);
            });
    }
}(),
function()
{
    P.absolutify = function(e, t, n)
    {
        return e ? 0 === e.lastIndexOf("http://", 0) || 0 === e.lastIndexOf("https://", 0) ? e : (t = t || window.location.protocol, n = n || window.location.hostname, t + "//" + n + e) : e;
    },
    P.normalizeUrl = function(e)
    {
        if ("/" === e.substr(0, 0))
        {
            return e;
        }
        var t = P.absolutify("/");
        return 0 === e.lastIndexOf(t, 0) ? e.substr(t.length - 1) : e;
    },
    P.getCurrentUrl = function()
    {
        return window.location.pathname + ("?" === window.location.search ? "" : window.location.search);
    };
    var e = function(e)
    {
        if (!e)
        {
            return null;
        }
        var t = document.createElement("a");
        return t.href = e,
        t;
    };
    P.isLocalUrl = function(t)
    {
        var n = e(t);
        if (!n)
        {
            return !1;
        }
        var i = /^https{0,1}:$/,
            o = i.test(n.protocol),
            s = n.host === window.location.host;
        return o && s;
    },
    P.isOffsiteUrl = function(e)
    {
        return !(!e || !e.match(/^https{0,1}:\/\//));
    };
}(),
function()
{
    P.scrollbarWidth = _.memoize(function()
    {
        var e = document.createElement("div");
        $(e).css({
            height: "100px",
            left: "100px",
            overflow: "scroll",
            position: "absolute",
            width: "100px"
        }),
        document.body.appendChild(e);
        var t = e.offsetWidth - e.clientWidth;
        return document.body.removeChild(e),
        t;
    }),
    P.preloadImage = function(e, t, n)
    {
        var i = new Image;
        i.src = e,
        i.onload = t || P.NOOP,
        i.onerror = n || P.NOOP;
    },
    P.loadModule = function(e, t)
    {
        var n = e.name;
        P.Loader.require([n],
            function(n)
            {
                t(new n(e));
            });
    },
    P.loadTutorial = function(e, t)
    {
        P.loadModule(t,
            function(t)
            {
                e.showInModal(t, {
                    mask_type: "dark"
                });
            });
    },
    jQuery.fn.positionAncestor = function(e)
    {
        var t = 0,
            n = 0;
        return e.length > 0 && this.each(function(i, o)
        {
            var s = $(o),
                r = s.offset();
            if (e[0] === window)
            {
                t = r.left,
                n = r.top;
            }
            else
            {
                var a = e.scrollLeft(),
                    l = e.scrollTop(),
                    u = e.offset();
                t = a + r.left - u.left,
                n = l + r.top - u.top;
            }
            return !1;
        }),
        {
            left: t,
            top: n
        };
    },
    P.toArgumentString = function(e)
    {
        var t = [];
        return _.each(e,
            function(e, n)
            {
                e = e && e.toString ? "" + e : JSON.stringify(e),
                t.push(n + "=" + e);
            }),
        t.join(", ");
    },
    P.getLoginUrl = function()
    {
        return "/login/?" + $.param({
            next: window.location.href
        });
    },
    P.getRegisterUrl = function()
    {
        return "/join/?" + $.param({
            next: window.location.href
        });
    },
    P.getResetPasswordOneClickUrl = function(e)
    {
        return "/login/reset/?" + $.param(e);
    },
    P.getQueryStringParams = function(e)
    {
        e = e || window.location.search.substring(1);
        var t = {};
        return _.each(e.split("&"),
            function(e)
            {
                var n = e.split("="),
                    i = decodeURIComponent(n[0]),
                    o = decodeURIComponent(n[1]);
                t[i] = o;
            }),
        t;
    };
    var e = /(<([^>]+)>)/gi;
    P.stripTags = function(t)
    {
        return t.replace(e, "");
    },
    P.historyNavigate = function(e, t)
    {
        P.app.historyManager.navigate(e, t || {});
    },
    P.keyCode = {
        BACKSPACE: 8,
        COMMA: 188,
        DELETE: 46,
        DOWN: 40,
        END: 35,
        ENTER: 13,
        ESCAPE: 27,
        HOME: 36,
        LEFT: 37,
        NUMPAD_ADD: 107,
        NUMPAD_DECIMAL: 110,
        NUMPAD_DIVIDE: 111,
        NUMPAD_ENTER: 108,
        NUMPAD_MULTIPLY: 106,
        NUMPAD_SUBTRACT: 109,
        PAGE_DOWN: 34,
        PAGE_UP: 33,
        PERIOD: 190,
        RIGHT: 39,
        SPACE: 32,
        TAB: 9,
        UP: 38
    },
    P.useHistory = function()
    {
        return !!(window.history && window.history.pushState && window.history.replaceState);
    },
    P.supportCSSTransitions = _.memoize(function()
    {
        var e = document.createElement("p").style,
            t = "transition" in e || "WebkitTransition" in e || "MozTransition" in e || "msTransition" in e || "OTransition" in e;
        return t;
    }),
    P.setTitlePrefix = function(e)
    {
        var t = document.title;
        t = t.replace(/^\(\w+\) /, ""),
        e && (t = "(" + e + ") " + t),
        document.title = t;
    };
}(),
function()
{
    P.requestAnimationFrameThrottled = function(e)
    {
        var t = !1;
        return function()
        {
            t || (t = !0, window.requestAnimationFrame(function()
            {
                e(),
                t = !1;
            }));
        };
    };
}(),
function()
{
    var e = [],
        t = function()
        {
            var t = e;
            e = [];
            for (var n = 0; n < t.length; n++)
            {
                t[n]();
            }
        },
        n = {
            scheduleFlush: P.requestAnimationFrameThrottled(t)
        };
    P.Errors.wrap(n, ["scheduleFlush"]),
    P.deferDomManipulation = function(t)
    {
        e.push(t),
        n.scheduleFlush();
    },
    P.stopwatch.wrapMethods(P, "P", ["deferDomManipulation"]);
}(),
function()
{
    P.trackRegisterAction = function(e)
    {
        var t = new P.Resource("UserRegisterTrackActionResource", {
            action: e
        });
        t.call("update", {
            error: function(e)
            {
                P.log("ERROR", "Call to UserRegisterTrackActionResource failed:", e);
            }
        });
    };
}(),
function()
{
    var e = 14,
        t = 10,
        n = 3,
        i = 236;
    P.Viewport = {
        height: 0,
        width: 0,
        init: function()
        {
            this.on(P.CONST.EVENT_RESIZE, this._onResize, this),
            $(window).on("resize", _.debounce(_.bind(this._cacheWindowSize, this), 200)),
            this._cacheWindowSize(),
            this._updateBodyColumns();
        },
        _cacheWindowSize: function()
        {
            var e = $(window),
                t = e.height(),
                n = e.width();
            (t !== this.height || n !== this.width) && (this.height = t, this.width = n, this.trigger(P.CONST.EVENT_RESIZE));
        },
        _onResize: function()
        {
            this._updateBodyColumns();
        },
        _updateBodyColumns: function()
        {
            this.setBodyColumns(this._calcBodyColumns());
        },
        _calcBodyColumns: function()
        {
            return Math.min(Math.max(Math.floor(this.width / (i + e)), n), t);
        },
        setBodyColumns: function(e)
        {
            if (e !== this.numColumns)
            {
                var t = $("body");
                if (t.length)
                {
                    var n = "columns-" + this.numColumns,
                        i = "columns-" + e;
                    t.removeClass(n).addClass(i),
                    this.numColumns = e,
                    this.trigger(P.CONST.EVENT_BODY_COLUMN_CHANGE);
                }
            }
        },
        isOverlapping: function(e, t)
        {
            if (t || (t = 0), !e.getBoundingClientRect)
            {
                return !0;
            }
            var n = e.getBoundingClientRect(),
                i = n.right - n.left,
                o = n.bottom - n.top;
            return i > 0 && o > 0 && n.top < this.height + t && n.bottom > -t && n.left < this.width + t && n.right > -t ? !0 : !1;
        }
    },
    _.extend(P.Viewport, Backbone.Events),
    P.Errors.wrap(P.Viewport, ["isOverlapping"]);
}(),
function()
{
    P.window = {
        open: function(e, t, n, i)
        {
            var o = this._makeWindowOptions(n, i);
            P.debugWindow = window.open(e, t, o);
        },
        _makeWindowOptions: function(e, t)
        {
            var n = screen.width,
                i = screen.height,
                o = Math.round((n - e) / 2),
                s = i > t ? Math.round((i - t) / 2) : 0;
            return "scrollbars=yes,resizable=yes,toolbar=no,location=yes,width=" + e + ",height=" + t + "," + "left=" + o + ",top=" + s;
        }
    };
    var e = function(e, t)
    {
        return P.Errors.ENABLE_WRAPPING ?
            function(n, i, o)
            {
                if (n)
                {
                    var s = e + ":" + o,
                        r = _.isFunction(n) ? P.Errors.wrapFn(s, n) : n;
                    return t(r, i);
                }
            } : t;
    };
    window.setTimeout = e("setTimeout", window.setTimeout),
    window.setInterval = e("setInterval", window.setInterval);
}(),
function()
{
    var e = "noScroll",
        t = function()
        {
            this.scrollStack = [!0];
        };
    t.prototype = {
        pushScrolling: function(e)
        {
            return this.push().setScrolling(e),
            this;
        },
        pop: function()
        {
            return this.scrollStack.length <= 1 ? (P.log("ERROR", "Tried to pop with only one item on stack.  Mismatched push and pops?"), void 0) : (this.scrollStack.pop(), this.updateElement(), this);
        },
        setScrolling: function(e)
        {
            return this.scrollStack[this.scrollStack.length - 1] = e,
            this.updateElement(),
            this;
        },
        push: function()
        {
            return this.scrollStack.push(this.peek()),
            this;
        },
        peek: function()
        {
            return this.scrollStack[this.scrollStack.length - 1];
        },
        updateElement: function()
        {
            var t = this.peek();
            $("body").toggleClass(e, !t);
        }
    },
    P.Body = new t,
    window.P_TEST_MODE && (P.Body.constructor = t);
}(),
function()
{
    var e = " loaded",
        t = " fade";
    P.Lazy = {
        imageLoad: function(n)
        {
            var i = e;
            P.Viewport.isOverlapping(n) && (i += t),
            P.deferDomManipulation(function()
            {
                n.className += i;
            });
        }
    };
}(),
function()
{
    var e = "sticky",
        t = "absolute",
        n = "below",
        i = t + " " + n,
        o = i + " " + e,
        s = e,
        r = 0,
        a = 1,
        l = 2;
    P.Sticky = function(e, t)
    {
        this.$el = e,
        this.elementHeight = null,
        this.headerHeight = t.headerHeight,
        this.boundElementHeight = null,
        this.$boundTo = t.$boundTo,
        this.$scrollable = t.$scrollable,
        _.bindAll(this, "updateFixed", "_onScroll"),
        this.$scrollable.on("scroll.sticky", this._onScroll),
        this.pendingScrollRAF = !1,
        this.lastState = null;
        var n = this;
        P.deferDomManipulation(function()
        {
            n.elementHeight = e.height(),
            n.boundElementHeight = n.$boundTo.height();
        });
    },
    _.extend(P.Sticky.prototype, Backbone.Events, {
        destroy: function()
        {
            this.$scrollable.off("scroll.sticky", this.updateFixed);
        },
        unSticky: function()
        {
            this.destroy();
        },
        _onScroll: function()
        {
            if (!this.pendingScrollRAF)
            {
                var e = this;
                P.deferDomManipulation(function()
                {
                    return e.scrollTop = e.$scrollable.scrollTop(),
                    e.scrollTop === e.lastScrollTop ? (e.pendingScrollRAF = !1, void 0) : (e.updateFixed(), e.lastScrollTop = e.scrollTop, e.pendingScrollRAF = !1, void 0);
                }),
                this.pendingScrollRAF = !0;
            }
        },
        updateFixed: function()
        {
            var t, n = $(window),
                s = n.scrollTop(),
                u = s,
                c = this.$boundTo.offset().top - this.headerHeight,
                d = this.$boundTo.offset().top + this.boundElementHeight - this.headerHeight;
            t = u >= c && u <= d ? a : u >= d ? l : r,
            t !== this.lastState && (t === a ? (this.$el.css("top", "").addClass(e).removeClass(i), this.trigger(P.CONST.EVENT_STICKY_FIXED, !0)) : t === l ? (this.$el.removeClass(e), this.trigger(P.CONST.EVENT_STICKY_FIXED, !1), this.handleReachingBottom()) : t === r && (this.$el.removeClass(o), this.trigger(P.CONST.EVENT_STICKY_NORMAL), this.trigger(P.CONST.EVENT_STICKY_FIXED, !1))),
            this.lastState = t;
        },
        handleReachingBottom: function()
        {
            if (!this.$el.hasClass(i))
            {
                var e = this.boundElementHeight || 0,
                    o = parseInt(this.$el.css("top").split("px")[0], 10) || 0;
                this.$el.addClass(t + " " + n).css("top", e + o + 1);
            }
        }
    }),
    jQuery.fn.sticky = function(t)
    {
        return this.each(function(n, i)
        {
            var o = $(i),
                r = o.data(s);
            if (r && (r.destroy(), o.removeData(e)), "unsticky" === t)
            {
                ;
            }
            else if ("object" === typeof t)
            {
                var a = t.$scrollable,
                    l = t.$boundTo,
                    u = t.headerHeight || 0;
                a && (r = new P.Sticky(o, a, l, u), o.data(s, r));
            }
        }),
        this;
    };
}(),
jQuery.fn.overflowingText = function()
{
    return this.each(function(e, t)
    {
        if (t.offsetHeight < t.scrollHeight || t.offsetWidth < t.scrollWidth)
        {
            var n = $(t);
            n.addClass(P.CONST.OVERFLOWING_TEXT_OVERFLOWING_CLASS);
        }
    }),
    this;
};
var ATTR_IS_HOVERING = "data-is-hovering";
jQuery.fn.initHovering = function()
{
    return this.each(function(e, t)
    {
        $(t).hover(function()
        {
            $(t).attr(ATTR_IS_HOVERING, "true");
        },
            function()
            {
                $(t).attr(ATTR_IS_HOVERING, "");
            }).attr(ATTR_IS_HOVERING, "");
    }),
    this;
},
jQuery.fn.isHovering = function()
{
    return $(this).attr(ATTR_IS_HOVERING);
},
function()
{
    function e(e)
    {
        P.log("gaqPush", e),
        window._gaq.push(e);
    }
    window._gaq = window._gaq || [],
    P.initializeGA = function(t)
    {
        var n = document.createElement("script");
        n.type = "text/javascript",
        n.async = !0,
        n.src = ("https:" === document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js",
        (document.getElementsByTagName("head")[0] || document.getElementsByTagName("body")[0]).appendChild(n),
        P.DEBUG && (e(["_setSampleRate", 100]), e(["_setSiteSpeedSampleRate", 100])),
        e(["_setAccount", t]);
    },
    P.trackGALoggedInUser = function(t)
    {
        var n = t ? "logged in" : "logged out";
        e(["_setCustomVar", 1, "is_logged_in", n, 2]);
    },
    P.trackGAPageview = function(t)
    {
        t && e(["_setCustomVar", 2, "page_name", t, 1]);
        var n = document.URL;
        n.replace(/email=[^&]+/, "email=*"),
        e(["_trackPageview", n]);
    };
    var t = function(t, n, i, o)
    {
        e(["_trackEvent", t, n, i, o]);
    };
    P.trackGAEvent = t;
    var n = function(t, n, i, o)
    {
        var s = 100;
        e(["_trackTiming", t, n, o, i, s]);
    };
    P.pubsub.subscribe(P.CONST.PUBSUB_CHANNEL_ANALYTICS, P.CONST.PUBSUB_TOPIC_TIMING_METRICS_EMITTED,
        function(e, i, o)
        {
            var s = o;
            _.each(s.getCounts(),
                function(e, n)
                {
                    t(s.category, s.subCategory, n, e);
                }),
            _.each(s.getTimes(),
                function(e, t)
                {
                    n(s.category, s.subCategory, t, e);
                });
        });
}(),
P.Event = function(e, t, n)
{
    this.type = e,
    this.target = t,
    this.currentTarget = t,
    this.data = n || {};
    var i = !1;
    this.stopPropagation = function()
    {
        i = !0;
    },
    this.shouldPropagate = function()
    {
        return !i;
    };
},
function()
{
    P.Loader = {
        require: require,
        define: define
    },
    delete define.amd,
    delete require.amd;
}(),
function()
{
    var e = P.Logger.getLogger("TutorialManager"),
        t = {
            existingUser: {
                stepNames: ["WelcomeStep", "HomefeedStep", "CategoriesStep", "ProfileStep", "PinterestLogoStep"],
                nextUrl: "/",
                canExit: !0,
                onUserExit: function(e)
                {
                    0 === e && P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_TUTORIAL, P.CONST.PUBSUB_TOPIC_TUTORIAL_CATEGORIES);
                }
            },
            newUser: {
                stepNames: ["WelcomeStep", "HomefeedStep", "CategoriesStep", "ProfileStep", "PinterestLogoStep"],
                nextUrl: "/",
                canExit: !1,
                onUserExit: P.NOOP
            }
        },
        n = "tutorial",
        i = "Tutorial";
    P.TutorialManager = function()
    {
    },
    P.TutorialManager.prototype = {
        startTutorial: function(e)
        {
            this._start(e, !0);
        },
        resumeTutorial: function()
        {
            var e = this._getStoredData();
            e && e.name && this._start(e.name, !1);
        },
        _start: function(e, n)
        {
            var o = t[e];
            o && (this._clear(n), this._isActive = !0, this.tutorialName = e, this.tutorialClassName = this.tutorialName + i, $("body").addClass(this.tutorialClassName), this.tutorial = o, this.allStepNames = this.tutorial.stepNames, this.numTotalSteps = this.tutorial.stepNames.length, this._setupModal(), this._setStep(this._getStoredStep() || this.allStepNames[0]));
        },
        isTutorialActive: function()
        {
            return this._isActive;
        },
        _setupModal: function()
        {
            var e = this,
                t = {
                    name: "Modal",
                    options: {
                        mask_type: "dark",
                        can_dismiss: !1
                    }
                };
            P.loadModule(t,
                function(t)
                {
                    e.modal = t,
                    e.modal.render(),
                    e.modal.childListen(P.CONST.EVENT_NEXT, _.bind(e._next, e)),
                    e.modal.childListen(P.CONST.EVENT_PREVIOUS, _.bind(e._previous, e)),
                    P.ModalManager.instance().showModal(e.modal);
                });
        },
        _next: function()
        {
            var e = this._getStepIndex(this.currentStep);
            return this.currentStep === _.last(this.allStepNames) ? (this._endTutorial(!0), void 0) : (this._setStep(this.allStepNames[e + 1]), void 0);
        },
        _previous: function()
        {
            var t = this._getStepIndex(this.currentStep);
            return 0 === t ? (e.logToServer(P.Logger.SERVER_LOG_TYPE.LOG, "get", {
                type: "tutorial",
                tutorial: this.tutorialName,
                step: this.currentStep,
                step_number: t,
                action: "exit"
            }), this.tutorial.onUserExit(t), this._endTutorial(), void 0) : (this._setStep(this.allStepNames[t - 1]), void 0);
        },
        _endTutorial: function()
        {
            var e = this,
                t = function()
                {
                    var t = e.tutorial.nextUrl;
                    e._clear(!0),
                    t && P.historyNavigate(t);
                };
            this.currentModule ? this.currentModule.onExit(function()
            {
                e.currentModule.cleanHighlightedElements(),
                t();
            }) : t();
        },
        _setStep: function(e)
        {
            if (P.log("set step from", this.currentStep, "to", e), e !== this.currentStep)
            {
                if (this.currentStep = e, this._saveCurrentStep(), !this.currentModule)
                {
                    return this._loadModuleForStep(this.currentStep),
                    void 0;
                }
                var t = this;
                this.currentModule.onExit(function()
                {
                    t.currentModule.cleanHighlightedElements(),
                    t._loadModuleForStep(e);
                });
            }
        },
        _loadModuleForStep: function(e)
        {
            var t = this,
                n = {
                    name: "tutorials." + e,
                    options: {
                        tutorial_name: this.tutorialName,
                        current_step: this._getStepIndex(e),
                        total_steps: this.numTotalSteps,
                        can_exit: this.tutorial.canExit
                    }
                };
            P.loadModule(n,
                function(e)
                {
                    var n = t.currentModule;
                    t.currentModule = e,
                    e.onEnter(function()
                    {
                        e.render(function()
                        {
                            t.modal.setModule(e),
                            n && n.destroy(),
                            e.setModalPosition(),
                            e.onShow();
                        });
                    });
                });
        },
        _getStepIndex: function(e)
        {
            var t = _.indexOf(this.allStepNames, e);
            return -1 !== t ? t : 0;
        },
        _getStoredStep: function()
        {
            var e = this._getStoredData();
            return e && e.name !== this.tutorialName && (this._clearStoredData(), e = null),
            e && e.step || null;
        },
        _getStoredData: function()
        {
            return P.SessionStorage.getItem(n);
        },
        _saveCurrentStep: function()
        {
            P.SessionStorage.setItem(n, {
                name: this.tutorialName,
                step: this.currentStep
            });
        },
        _clear: function(e)
        {
            this.tutorial && (this._isActive = !1, $("body").removeClass(this.tutorialClassName), this.tutorialName = null, this.tutorialClassName = null, this.tutorial = null, this.allStepNames = null, this.numTotalSteps = null, this._destroyModal(), e && this._clearStoredData());
        },
        _clearStoredData: function()
        {
            P.SessionStorage.removeItem(n);
        },
        _destroyModal: function()
        {
            this.modal.destroy(),
            this.modal = null;
        }
    };
    var o = null;
    P.TutorialManager.instance = function()
    {
        return o || (o = new P.TutorialManager),
        o;
    };
}(),
function()
{
    var e = 300,
        t = "fadeIn",
        n = "fadeOut",
        i = t + " " + n,
        o = "loading",
        s = 300,
        r = "moduleMask",
        a = "inModal",
        l = "notNavigatable",
        u = "savedScrollTop",
        c = _.invert(P.CONST.ErrorStrategy),
        d = 0,
        h = function(e, t, n)
        {
            var i = "other";
            this.object = e,
            this.event = t,
            this.fn = n,
            this.object instanceof P.Module ? this.id = this.object.cid : (this.id = i + d, d += 1);
        };
    P.Module = Backbone.View.extend({
        className: "Module",
        constructor: function(e)
        {
            Backbone.View.apply(this, arguments),
            this._build(e);
        },
        _configure: function()
        {
            this.parent = null,
            this.children = [],
            this._childrenIdMap = {},
            this._listeners = {},
            this._pubsubHandlers = {},
            this.inDom = !1,
            this.contentReady = !1,
            this._moduleTree = null,
            this._html = null,
            this._pendingRenderRequest = !1,
            this._pendingRenderAppendRequest = !1,
            this.extraState = {},
            Backbone.View.prototype._configure.apply(this, arguments);
        },
        _ensureElement: function()
        {
            if (this.el)
            {
                this.setElement(this.el, !1);
            }
            else
            {
                var e = this.attributes || {};
                if (!e["class"])
                {
                    var t = ["Module"],
                        n = this.className.replace(/\./g, "-");
                    t.push(n),
                    e["class"] = t.join(" ");
                }
                var i = $(document.createElement(this.tagName));
                i.attr(e),
                this.setElement(i, !1);
            }
        },
        initialize: function()
        {
        },
        setAsMainModule: function(e, t, n, i, o)
        {
            return this.errorStrategy = P.CONST.ErrorStrategy.SHOW,
            this.hasSameOptions(e, t) && this.contentReady && !this._forceRefresh(n) ? (i(), void 0) : (this.empty(), this._forceRefresh(n) && (this.extraState = {}), this.setOptions(e), this.setResource(t), this.performTransition(n, i, o), void 0);
        },
        _forceRefresh: function(e)
        {
            return e && e.evt && e.evt.data && e.evt.data.forceRefresh;
        },
        performTransition: function(e, t)
        {
            this.render(t, t);
        },
        setResource: function(e)
        {
            (!e || _.isEqual(e, {})) && (e = P.Resource.NOOP_RESOURCE),
            this.resource = new P.Resource(e.name, e.options);
        },
        setOptions: function(e)
        {
            var t = this.options;
            this.options = e || {},
            this.onOptionsChanged(t, this.options);
        },
        setModal: function(e)
        {
            e ? this.$el.addClass(a) : this.$el.removeClass(a),
            this.modal = e,
            e && this.onAddedToModal(e);
        },
        prependChild: function(e)
        {
            this.$el.prepend(e.getElement()),
            this.addChild(e, 0);
        },
        appendChild: function(e)
        {
            this.insertChild(e, this.$el);
        },
        insertChild: function(e, t, n)
        {
            t.append(e.getElement()),
            this.addChild(e, n);
        },
        removeChild: function(e)
        {
            if (e.parent === this)
            {
                e.parent = null,
                this._removeListenersOnModule(e),
                this.children = _.filter(this.children,
                    function(t)
                    {
                        return e !== t;
                    }),
                e.id && delete this._childrenIdMap[e.id];
                var t = e.getParentElement();
                e.detachElement(),
                e.onRemoved(),
                this.onChildRemoved(e, t);
            }
        },
        getChildByElement: function(e)
        {
            var t = _.find(this.children,
                function(t)
                {
                    return t.$el.is(e);
                });
            return t;
        },
        getChildByModuleName: function(e)
        {
            var t = _.find(this.children,
                function(t)
                {
                    return t.className === e;
                });
            return t;
        },
        getChildrenByModuleName: function(e)
        {
            var t = _.filter(this.children,
                function(t)
                {
                    return t.className === e;
                });
            return t;
        },
        getChildById: function(e)
        {
            return this._childrenIdMap[e];
        },
        removeChildById: function(e)
        {
            var t = this.getChildById(e);
            t && t.remove();
        },
        remove: function()
        {
            this.parent && this.parent.removeChild(this);
        },
        detachElement: function()
        {
            this.remove(),
            this.$el.detach(),
            this.inDom && this._setInDom(!1);
        },
        destroy: function()
        {
            this.empty(),
            this.detachElement(),
            this._removeListeners(),
            this._subscribers && _.each(this._subscribers,
                function(e)
                {
                    e.unsubscribe();
                }),
            this.undelegateEvents(),
            this.destroyed = !0,
            this.onDestroyed(),
            this.triggerEvent(P.CONST.EVENT_DESTROYED);
        },
        destroyIfEmpty: function()
        {
            return this.contentReady && this.isEmpty() ? (this.destroy(), !0) : !1;
        },
        empty: function()
        {
            for (this.$el.empty(); this.children.length;)
            {
                this.children[0].destroy();
            }
            this.children = [],
            this._childrenIdMap = {},
            this.contentReady = !1,
            this.onEmpty();
        },
        onEmpty: P.NOOP,
        onRendered: P.NOOP,
        onContentReady: P.NOOP,
        onAdded: P.NOOP,
        onRemoved: P.NOOP,
        onDestroyed: P.NOOP,
        onChildAdded: function()
        {
        },
        onChildRemoved: function()
        {
        },
        onChildRendered: P.NOOP,
        onAddedToDom: P.NOOP,
        onRemovedFromDom: P.NOOP,
        onPubSubMessage: function()
        {
        },
        onOptionsChanged: function()
        {
        },
        onAddedToModal: function()
        {
        },
        handleError: function(e)
        {
            var t = this.getFullName();
            this.errorStrategy === P.CONST.ErrorStrategy.REMOVE ? (this.log.warn("Removing module because of error."), this.destroy()) : this.errorStrategy === P.CONST.ErrorStrategy.BUBBLE && (this.log.warn("Bubbling up the error."), this.parent.handleError(e)),
            this.log.warn("Error in", t, "\n", "Code:", e.code, "\n", "Strategy:", c[this.errorStrategy], "\n", "HTTP Status:", e.http_status, "\n", e.message),
            this.triggerEvent(P.CONST.EVENT_ERROR, e, this);
        },
        getSubscriber: function(e)
        {
            if (this._subscribers || (this._subscribers = {}), !this._subscribers[e])
            {
                var t = new P.pubsub.Subscriber(e, {
                    handler: this._handlePubsub,
                    scope: this,
                    name: this.className
                });
                this._subscribers[e] = t;
            }
            return this._subscribers[e];
        },
        pubsubSubscribe: function(e, t)
        {
            var n = this.getSubscriber(e);
            n.subscribe.apply(n, _.keys(t)),
            this._pubsubHandlers[e] || (this._pubsubHandlers[e] = {}),
            _.extend(this._pubsubHandlers[e], t);
        },
        pubsubUnsubscribe: function(e)
        {
            var t = _.tail(arguments),
                n = this.getSubscriber(e);
            n.unsubscribe.apply(n, t);
        },
        _handlePubsub: function(e, t, n)
        {
            var i = (this._pubsubHandlers[e] || {})[t];
            i && i.call(this, e, t, n),
            this.onPubSubMessage(e, t, n);
        },
        ensureAuthentication: function()
        {
            return P.currentUser.isAuthenticated() ? !0 : (this.navigate(P.getRegisterUrl()), !1);
        },
        getFullName: function()
        {
            for (var e = [this.toString(!0)], t = this; t.parent;)
            {
                t = t.parent,
                e.unshift("" + t);
            }
            return e.join(">");
        },
        toString: function(e)
        {
            var t = this.className,
                n = [];
            return e && this.options && n.push(P.toArgumentString(this.options)),
            this.resource && "NoopResource" !== this.resource.name && n.push("resource=" + ("" + this.resource)),
            t + "(" + n.join(", ") + ")";
        },
        getHeight: function(e)
        {
            return e = e || !1,
            this.$el.outerHeight(e);
        },
        getWidth: function(e)
        {
            return e = e || !1,
            this.$el.outerWidth(e);
        },
        getParentElement: function()
        {
            return this.$el.parent();
        },
        getElement: function()
        {
            return this.$el;
        },
        getScrollableElement: function()
        {
            return this.getScrollableElementForElement(this.$el);
        },
        getScrollableElementForElement: function(e)
        {
            var t = this.getOwnedScrollables();
            if (t.length > 0)
            {
                var n = e;
                n = n.add(e.parentsUntil(this.$el)),
                n = n.add(this.$el);
                var i = n.filter(t);
                if (i.length > 0)
                {
                    return i.first();
                }
            }
            return this.parent ? this.parent.getScrollableElementForElement(this.$el.parent()) : $(window);
        },
        listen: function(e, t, n)
        {
            var i = this,
                o = function()
                {
                    n.apply(i, arguments);
                };
            e.on(t, o);
            var s = new h(e, t, o);
            return this._listeners[s.id] || (this._listeners[s.id] = []),
            this._listeners[s.id].push(s),
            s;
        },
        childListen: function(e, t)
        {
            return this.listen(this, "child:" + e, t);
        },
        delegateEvents: function()
        {
            if (!this.__wrapEvents)
            {
                this.events = this.events || {},
                this.events["click a"] = "_handleLinkClick";
                var e = this,
                    t = {};
                _.each(this.events,
                    function(n, i)
                    {
                        t[i] = _.isFunction(n) ? P.Errors.wrapFn("eventFunction", n) : P.Errors.wrapFn(n,
                            function()
                            {
                                return P.state.activeTarget = e,
                                e[n].apply(e, arguments);
                            });
                    }),
                this.events = t,
                this.__wrapEvents = !0;
            }
            return Backbone.View.prototype.delegateEvents.call(this);
        },
        navigate: function(e, t, n)
        {
            var i = {
                url: e,
                $el: t
            };
            n && (i.forceRefresh = 1),
            this.triggerEvent("navigate", i, !0) && (this.log.debug("Navigate event wasn't prevented. Navigating to:", e), P.historyNavigate(e));
        },
        showInModal: function(e, t)
        {
            this.triggerEvent("modal", {
                    module: e,
                    extraOptions: t
                },
                !0) && (this.log.debug("Modal event wasn't prevented. Telling modalManager to open:", e), P.ModalManager.instance().showInModal(e, t || {},
                    this));
        },
        removeListener: function(e)
        {
            e.object.off(e.event, e.fn),
            this._listeners[e.id] = _.filter(this._listeners[e.id],
                function(t)
                {
                    return e !== t;
                });
        },
        triggerEvent: function(e, t, n)
        {
            var i = new P.Event(e, this, t);
            if (this.trigger(e, i), i.shouldPropagate() && n)
            {
                for (var o = new P.Event("child:" + e, this, t), s = this.parent; s && o.shouldPropagate();)
                {
                    s.trigger.call(s, o.type, o),
                    o.currentTarget = s,
                    s = s.parent;
                }
                return o.shouldPropagate();
            }
            return i.shouldPropagate();
        },
        _removeListenersOnModule: function(e)
        {
            _.each(this._listeners[e.cid],
                function(e)
                {
                    e.object.off(e.event, e.fn);
                }),
            delete this._listeners[e.cid];
        },
        showLoading: function(e)
        {
            if (!this.loading)
            {
                this.loading = !0;
                var t = this._getLoadingSpinner();
                t && t.spin(this.$el),
                this.$el.addClass(o),
                e && this.showMask();
            }
        },
        hideLoading: function()
        {
            this._spinner && (this._spinner.stop(), this._spinner = null),
            this.loading && (this.loading = !1, this.$el.removeClass(o), this.hideMask());
        },
        showMask: function()
        {
            var e = this.getMask();
            e.css({
                left: 0,
                top: 0,
                width: this.getWidth(),
                height: this.getHeight()
            }),
            e.addClass("visible");
        },
        hideMask: function()
        {
            this.getMask().removeClass("visible");
        },
        getMask: function()
        {
            var e = this.$("> ." + r);
            return e.get(0) || (e = $("<div></div>").addClass(r), this.$el.prepend(e)),
            e;
        },
        show: function()
        {
            this.$el.show();
        },
        hide: function()
        {
            this.$el.hide();
        },
        fadeIn: function(i)
        {
            this.$el.removeClass(n).addClass(t);
            var o = function()
            {
                i && i();
            };
            setTimeout(o, e);
        },
        fadeOut: function(i)
        {
            this.$el.removeClass(t).addClass(n);
            var o = function()
            {
                i && i();
            };
            setTimeout(o, e);
        },
        clearFades: function()
        {
            this.$el.removeClass(i);
        },
        _getLoadingSpinner: function()
        {
            if (!this._spinner)
            {
                var e = this.getLoadingSpinnerOptions();
                if (null === e)
                {
                    return null;
                }
                this._spinner = new P.Spinner(e);
            }
            return this._spinner;
        },
        getLoadingSpinnerOptions: function()
        {
            return {};
        },
        render: function(e, t)
        {
            var n = this.getParentElement();
            return 0 === n.length && (n = $(document.body)),
            this._render(n, e, t);
        },
        renderAppend: function(e, t)
        {
            var n = this;
            return !this.contentReady || this._pendingRenderRequest || this._pendingRenderAppendRequest || this.resource.atEnd() ? !1 : (this._fetch(!1, !0,
                function()
                {
                    n._pendingRenderAppendRequest = !1,
                    e && e.call(n),
                    n.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
                },
                function()
                {
                    n._pendingRenderAppendRequest = !1,
                    t && t.call(n),
                    n.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
                },
                function(e, t)
                {
                    "abort" === t && (n._pendingRenderAppendRequest = !1);
                }), this._pendingRenderAppendRequest = !0, !0);
        },
        renderAbort: function()
        {
            return this._pendingRenderRequest ? (this.resource.abort(), !0) : !1;
        },
        _render: function(e, t, n)
        {
            if (this._pendingRenderRequest)
            {
                return !1;
            }
            this._pendingRenderAppendRequest && this.resource.abort();
            var i = this,
                o = setTimeout(function()
                {
                    i.showLoading(),
                    o = null;
                },
                    s, "_render Loading"),
                r = function()
                {
                    o ? clearTimeout(o) : i.hideLoading();
                },
                a = function()
                {
                    i.rendered = !0,
                    i._pendingRenderRequest = !1,
                    r(),
                    i.onRendered(),
                    i.parent && i.parent.onChildRendered(i),
                    t && t.call(i),
                    i.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
                },
                l = function()
                {
                    i._pendingRenderRequest = !1,
                    r(),
                    n && n.call(i);
                },
                u = function(e, t)
                {
                    "abort" === t && (i._pendingRenderRequest = !1, r());
                };
            return this._fetch(!1, !1, a, l, u),
            this._pendingRenderRequest = !0,
            this._pendingRenderRequest;
        },
        _fetch: function(e, t, n, i, o)
        {
            var s = this;
            this.resource || this.setResource(null),
            t || this.resource.resetBookmark(),
            this.resource.call("get", {
                options: {
                    module: {
                        name: this.className,
                        options: this.options,
                        append: t,
                        errorStrategy: this.errorStrategy
                    }
                },
                success: function(e)
                {
                    s.loadFromModuleTree(e.module.html, e.module.tree, t, n);
                },
                error: function(e, n)
                {
                    s.loadFromModuleTree(n.module.html, n.module.tree, t, i);
                },
                complete: o
            });
        },
        loadFromModuleTree: function(e, t, n, i)
        {
            var o = $(e),
                s = this;
            this.options.is_template_module && (this._html = e, this._moduleTree = t),
            P.deferDomManipulation(P.stopwatch.wrapContinuation("Module._fetch build",
                function()
                {
                    s._build(_.extend({},
                        t, {
                            parent: s.parent,
                            el: o,
                            append: n,
                            complete: i
                        }));
                }));
        },
        _build: function(e)
        {
            if (P.stopwatch.setNote("className", this.className), e = e || {},
            e.complete = e.complete || P.NOOP, e.el && !e.append && (this.contentReady = !1), e.id && (this.id = e.id), e.data && (this.data = e.data), e.extraData && (this.extraData = e.extraData), e.options && this.setOptions(e.options), !e.resource || e.error && e.append || this.setResource(e.resource), e.el)
            {
                var t = e.el;
                if (e.append)
                {
                    this.$el.append(t);
                }
                else
                {
                    var n = !!document.getElementById(t.attr("id")),
                        i = !this.inDom && n;
                    this.inDom = this.inDom || n,
                    this._replaceElement(t),
                    this.$el.removeAttr("id"),
                    i && this.onAddedToDom();
                }
            }
            if (e.parent && e.parent.addChild(this), _.isUndefined(e.errorStrategy) || null === e.errorStrategy || (this.errorStrategy = e.errorStrategy), e.error)
            {
                return e.error.target = this,
                this.handleError(e.error),
                e.complete.call(this),
                void 0;
            }
            if (e.async)
            {
                return this.render(e.complete),
                void 0;
            }
            var o = this,
                s = e.children,
                r = _.pluck(s, "name");
            P.Loader.require(r,
                function()
                {
                    var t = _.object(r, arguments);
                    s && s.length > 0 && _.each(s,
                        function(e)
                        {
                            var n = $("#" + e.uid, o.$el),
                                i = t[e.name];
                            new i(_.extend(e, {
                                parent: o,
                                el: n
                            }));
                        }),
                    e.el && !e.append && (o.contentReady = !0, o.onContentReady()),
                    e.complete.call(o);
                });
        },
        addChild: function(e, t)
        {
            var n = "undefined" === typeof t && -1 || t;
            e.parent !== this && (e.parent && e.remove(), e.parent = this, -1 === n ? this.children.push(e) : this.children.splice(n, 0, e), e.id && (this._childrenIdMap[e.id] = e), e.onAdded(), this.onChildAdded(e, t), this.inDom && e._setInDom(!0));
        },
        isEmpty: function()
        {
            return !$.trim(this.$el.html()) && !this.children.length;
        },
        isInModal: function()
        {
            return !!this.modal;
        },
        loadFromData: function()
        {
            this.log.error("override method loadFromData");
        },
        hasSameOptions: function(e, t)
        {
            var n = this.hasSameModuleOptions(e),
                i = this.hasSameResourceOptions(t);
            return this.log.debug("has same options? ", n, this.options, e, i, !this.resource || this.resource.options, t),
            n && i;
        },
        hasSameModuleOptions: function(e)
        {
            return e = e || {},
            _.isEqual(this.options, e);
        },
        hasSameResourceOptions: function(e)
        {
            (!e || _.isEqual(e, {})) && (e = P.Resource.NOOP_RESOURCE);
            var t = !this.resource && _.isEqual(e, P.Resource.NOOP_RESOURCE);
            return t || this.resource && this.resource.isEqual(e);
        },
        setChildId: function(e, t)
        {
            e.parent === this && (this.removeChildId(e), e.id = t, this._childrenIdMap[e.id] = e);
        },
        removeChildId: function(e)
        {
            e.id && e.parent === this && (delete this._childrenIdMap[e.id], delete e.id);
        },
        getOwnedScrollables: function()
        {
            return $();
        },
        saveExtraState: function(e)
        {
            if (e)
            {
                var t = this.getScrollableElement().scrollTop();
                this.extraState = {
                    scrollableElementScrollTop: t
                };
            }
            this.getOwnedScrollables().each(function(e, t)
            {
                var n = $(t),
                    i = n.scrollTop();
                n.data(u, i);
            }),
            _.each(this.children,
                function(e)
                {
                    e.saveExtraState(!1);
                });
        },
        restoreExtraState: function(e)
        {
            var t = this;
            if (e)
            {
                var n = this.extraState.scrollableElementScrollTop || 0;
                P.deferDomManipulation(P.stopwatch.wrapContinuation("Module.restoreExtraState callback",
                    function()
                    {
                        t.getScrollableElement().scrollTop(n);
                    }));
            }
            var i = t.getOwnedScrollables();
            i.length && P.deferDomManipulation(P.stopwatch.wrapContinuation("Module.restoreExtraState callback2",
                function()
                {
                    i.each(function(e, t)
                    {
                        var n = $(t),
                            i = n.data(u);
                        void 0 !== i && n.scrollTop(i);
                    });
                })),
            _.each(this.children,
                function(e)
                {
                    e.restoreExtraState(!1);
                });
        },
        _setInDom: function(e)
        {
            this.inDom !== e && (this.inDom = e, e ? this.onAddedToDom() : this.onRemovedFromDom(), _.each(this.children,
                function(t)
                {
                    t._setInDom(e);
                }));
        },
        _replaceElement: function(e)
        {
            e[0] !== this.$el[0] && (this.empty(), this.undelegateEvents(), e.css({
                display: this.$el.css("display")
            }), e.insertBefore(this.$el), this.$el.remove(), this.$el = e, this.el = e[0], this.delegateEvents());
        },
        _removeListeners: function()
        {
            _.each(this._listeners,
                function(e)
                {
                    _.each(e,
                        function(e)
                        {
                            e.object.off(e.event, e.fn);
                        });
                }),
            this._listeners = {};
        },
        _handleLinkClick: function(e)
        {
            var t = $(e.currentTarget),
                n = $(e.target),
                i = t.attr("href"),
                o = !n.hasClass(l) && !t.hasClass(l),
                s = t.hasClass("external"),
                r = n.attr("data-ga");
            return r && P.trackGAEvent(r, P.CONST.GA_ACTION_CLICK),
            o ? s ? (P.changeWindowLocation(i, !0), this.triggerEvent(P.CONST.EVENT_EXTERNAL_CLICK, null, !0), !1) : P.isOffsiteUrl(i) || !(e.which > 1 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) ? i && i.length && "#" !== i.charAt(0) && 0 !== i.lastIndexOf("javascript:", 0) ? (this.navigate(i, n, !!t.attr("data-force-refresh")), !1) : void 0 : void 0 : !1;
        },
        getDebugInfo: function()
        {
            return this.className;
        }
    }),
    P.Errors.wrap(P.Module.prototype, ["_build", "loadFromModuleTree", "render", "renderAppend"]),
    P.stopwatch.wrapMethods(P.Module.prototype, "Module", ["_build", "_fetch", "loadFromModuleTree", "render", "restoreExtraState", "showInModal"]);
    var p = P.Module.extend;
    _.extend(P.Module, {
        define: function(e, t, n)
        {
            return P.Loader.define(e, t,
                function()
                {
                    var t = n.apply(this, arguments);
                    return t.prototype.className = t.className = e,
                    t.prototype.log = P.Logger.getLogger(e),
                    t;
                });
        },
        extend: function(e, t)
        {
            return e && e.mixins && _.extend.apply(_, [e].concat(e.mixins)),
            p.call(this, e, t);
        }
    });
}(),
function()
{
    var e = /\$\{(\d+)\}/g,
        t = /\?\{(\w+)\}/g,
        n = /\$\{(\w+)\}/g,
        i = function(i, o, s, r)
        {
            return i = i.replace(t,
                function(e, t)
                {
                    return s[t] || "";
                }),
            i = i.replace(e,
                function(e, t)
                {
                    return o[parseInt(t, 10)];
                }),
            r && (i = i.replace(n,
                function(e, t)
                {
                    var n = r[t];
                    return o[n];
                })),
            i;
        },
        o = function(e, t, n, s)
        {
            var r = {};
            return _.each(e,
                function(e, a)
                {
                    var l = e;
                    _.isObject(e) ? l = o(e, t, n, s) : _.isString(e) && (l = i(e, t, n, s)),
                    r[i(a, t, n, s)] = l;
                }),
            r;
        };
    P.Router = function()
    {
        this.routes = [],
        this.lastUrl = window.location.href;
    },
    _.extend(P.Router.prototype, Backbone.Events, {
        start: function()
        {
            if (P.useHistory())
            {
                var e = this;
                if (_.each(P.ROUTES,
                    function(t)
                    {
                        e.addRoute(t);
                    }), window.history.replaceState)
                {
                    var t = $("link[rel=canonical]").attr("href");
                    if (window.location.href !== t)
                    {
                        var n = "state" in window.history ? window.history.state : {};
                        window.history.replaceState(n, document.title, t),
                        this.lastUrl = window.location.href;
                    }
                }
                $(window).on("popstate",
                    function(t)
                    {
                        P.log("popstate fired, lastUrl", e.lastUrl, " new URL ", window.location.href),
                        e.lastUrl === window.location.href ? P.log("ignoring spurious popstate event") : e.onStateChange(t),
                        e.lastUrl = window.location.href;
                    });
            }
        },
        navigate: function(e, t, n)
        {
            n = n || {},
            this.navigateData = n,
            t.trigger && ($("link[rel=canonical]").remove(), window.history.pushState({},
                document.title, e), this.lastUrl = window.location.href);
            var i = this.resolve(e);
            P.log("matchedRoute", i, e),
            i ? this.trigger("route", i) : this.trigger("404", e);
        },
        resolve: function(e)
        {
            var t = null,
                n = null;
            if (/\?/g.test(e))
            {
                var i = e.split("?");
                t = i[0],
                n = i[1];
            }
            else
            {
                t = e;
            }
            var o = window.location.hostname.split("pinterest.com")[0];
            if (o)
            {
                var s = P.CONST.SUBDOMAIN_PREFIXES[o.split(".")[0]];
                P.log("Has prefix: ", s),
                s && -1 === t.indexOf(s) && (t = s + t);
            }
            var r = decodeURIComponent(t),
                a = this,
                l = null;
            return _.find(this.routes,
                function(e)
                {
                    var t = e.uri.exec(r);
                    if (t)
                    {
                        var i = t.slice(1);
                        l = a.subRoute(e.route, i, n);
                    }
                    return l;
                }),
            l && P.stopwatch.setNote("routePattern", l.url),
            l;
        },
        addRoute: function(e)
        {
            var t = {
                uri: RegExp(e.url, "i"),
                route: e
            };
            this.routes.push(t);
        },
        subRoute: function(e, t, n)
        {
            var i = P.getQueryStringParams(n),
                s = {
                    navigateData: this.navigateData,
                    options: o(e.options, t, i, e.named),
                    resource: o(e.resource, t, i, e.named)
                };
            return _.defaults(s, e),
            this.navigateData = {},
            s;
        },
        onStateChange: function()
        {
            this.navigate(window.location.pathname, {
                trigger: !1
            });
        }
    }),
    P.changeWindowLocation = function(e, t)
    {
        t ? window.open(e, "_blank") : window.location.href = e;
    },
    P.navigate = function(e, t, n)
    {
        return e = P.normalizeUrl(e),
        P.isOffsiteUrl(e) ? (P.SafeLink.open(e), void 0) : P.useHistory() ? (t = t || {},
        n = n || {},
        t.fromNavigate = !0, P.router.navigate(e, {
                trigger: !0
            },
            t, n), void 0) : (P.changeWindowLocation(e), void 0);
    },
    P.stopwatch.wrapMethods(P, "P", ["navigate"]),
    P.stopwatch.wrapMethods(P.Router.prototype, "Router", ["navigate", "resolve", "onStateChange"]),
    P.router = new P.Router;
}(),
function()
{
    P.Style = function(e, t)
    {
        P.Style.addStyle(e, t);
    },
    P.Style.addStyle = function(e, t)
    {
        var n = e + "Styles",
            i = document.getElementById(n);
        i || (i = document.createElement("style"), i.setAttribute("type", "text/css"), i.setAttribute("id", n), document.getElementsByTagName("head")[0].appendChild(i)),
        i.styleSheet ? i.styleSheet.cssText = t : i.appendChild(document.createTextNode(t));
    };
}(),
function()
{
    "use strict";
    P.HoverIntent = function(e, t)
    {
        this.$el = e,
        this.options = _.extend({
                sensitivity: 10,
                enterDelay: 0,
                exitDelay: 0,
                interval: 40
            },
            t),
        this.$el.on("mouseenter mouseleave", _.bind(this._handleHover, this));
    },
    _.extend(P.HoverIntent.prototype, Backbone.Events, {
        _checkMouseEnter: function()
        {
            this._clearTimeout(),
            this._isMouseStill() ? this._onMouseEnterComplete() : (this._setPreviousXY(this._currX, this._currY), this._timeout = setTimeout(_.bind(this._checkMouseEnter, this), this.options.interval));
        },
        _clearTimeout: function()
        {
            this._timeout && (this._timeout = clearTimeout(this._timeout));
        },
        _handleHover: function(e)
        {
            this._clearTimeout();
            var t = this;
            "mouseenter" === e.type ? (this._onMouseEnterStart(), this.options.enterDelay ? (this._setPreviousXY(e.pageX, e.pageY), this.$el.on("mousemove.HoverIntent",
                    function(e)
                    {
                        t._setCurrentXY(e.pageX, e.pageY);
                    }), this._isEntered || (this._timeout = setTimeout(function()
                    {
                        t._checkMouseEnter();
                    },
                        this.options.enterDelay))) : this._onMouseEnterComplete()) : (this._onMouseOutStart(), this._isEntered && (this._timeout = setTimeout(function()
                        {
                            t._onMouseOutComplete();
                        },
                            this.options.exitDelay)));
        },
        _isMouseStill: function()
        {
            var e = Math.abs(this._prevX - this._currX),
                t = Math.abs(this._prevY - this._currY);
            return e || t || (e = 0, t = 0),
            e + t < this.options.sensitivity;
        },
        _onMouseEnterStart: function()
        {
            this.trigger(P.CONST.EVENT_HOVERINTENT_ENTER_START);
        },
        _onMouseEnterComplete: function()
        {
            this.$el.off("mousemove.HoverIntent"),
            this._isEntered = 1,
            this.trigger(P.CONST.EVENT_HOVERINTENT_ENTER_COMPLETE);
        },
        _onMouseOutStart: function()
        {
            this.$el.off("mousemove.HoverIntent"),
            this.trigger(P.CONST.EVENT_HOVERINTENT_OUT_START);
        },
        _onMouseOutComplete: function()
        {
            this._clearTimeout(),
            this._isEntered = 0,
            this.trigger(P.CONST.EVENT_HOVERINTENT_OUT_COMPLETE);
        },
        _setCurrentXY: function(e, t)
        {
            this._currX = e,
            this._currY = t;
        },
        _setPreviousXY: function(e, t)
        {
            this._prevX = e,
            this._prevY = t;
        }
    });
}(),
function()
{
    var e = P.Logger.getLogger("Resource"),
        t = "/resource/",
        n = "-end-";
    P.Resource = function(e, t)
    {
        _.bindAll(this, "onResponseSuccess", "onResponseError"),
        this.name = e,
        this.options = t;
    },
    _.extend(P.Resource.prototype, Backbone.Events, {
        setOptions: function(e)
        {
            this.options = e,
            this.trigger("setOptions", e);
        },
        set: function(e, t)
        {
            this.options[e] = t,
            this.trigger("set", e, t);
        },
        get: function(e)
        {
            return this.options[e] || null;
        },
        copy: function(e)
        {
            return new P.Resource(this.name, this.copyOptions(e));
        },
        copyOptions: function(e)
        {
            var t = _.clone(this.options);
            return t && e && delete t.bookmarks,
            t;
        },
        getUrl: function(e)
        {
            var n = t + this.name + "/";
            return e && (n = n + e + "/"),
            n;
        },
        call: function(t, n)
        {
            var i = this;
            n = n || {};
            var o = this.getUrl(t),
                s = n.success || P.NOOP,
                r = n.complete || P.NOOP,
                a = n.error,
                l = n.options || {},
                u = {
                    options: this.options
                };
            _.extend(u, l),
            u.context = P.CONTEXT,
            this.xhr && this.xhr.abort();
            var c = function(e)
            {
                var t = e.error;
                return e.resource_response && e.resource_response.error && (t = e.resource_response.error),
                t ? (d(t, e), void 0) : (i.onResponseSuccess(e), s(e), void 0);
            },
                d = function(e, t)
                {
                    return 403 !== e.http_status || P.currentUser.isAuthenticated() ? (i.onResponseError(e, t), a ? a(e, t) : P.showError(e.message), void 0) : (window.location.href = "/login/", void 0);
                },
                h = {
                    data: JSON.stringify(u),
                    source_url: P.getCurrentUrl()
                };
            P.state.activeTarget && (h.module_path = P.state.activeTarget.getFullName()),
            this.xhr = $.ajax({
                cache: !1,
                url: o,
                data: h,
                dataType: "json",
                type: "get" === t ? "get" : "post",
                success: P.stopwatch.wrapContinuation("Resource.call success", c),
                error: P.stopwatch.wrapContinuation("Resource.call error",
                    function(t, n)
                    {
                        if ("abort" !== n)
                        {
                            var i = null,
                                o = null,
                                s = -1;
                            if ((t.responseText || "").match(/^\{.*\}$/))
                            {
                                try
                                {
                                    o = JSON.parse(t.responseText),
                                    i = o.error && o.error.message,
                                    s = o.error && o.error.api_error_code;
                                }
                                catch(r)
                                {
                                    e.debug("Tried parsing the error response but failed");
                                }
                            }
                            d({
                                    message: i || P.string("errorMessage"),
                                    http_status: t.status,
                                    code: 3,
                                    api_error_code: s
                                },
                                o);
                        }
                    }),
                complete: P.stopwatch.wrapContinuation("Resource.call complete",
                    function()
                    {
                        i.xhr = null,
                        r.apply(null, arguments);
                    })
            }),
            this.trigger("call", t, u);
        },
        abort: function()
        {
            this.xhr && this.xhr.abort();
        },
        resetBookmark: function()
        {
            this.options && delete this.options.bookmarks;
        },
        atEnd: function()
        {
            var e = this.options.bookmarks;
            return e && _.last(e) === n;
        },
        onResponseSuccess: function(e)
        {
            e && e.resource && this.setOptions(e.resource.options),
            this.trigger("response", e),
            e.context && P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_APP_VERSION, e.context.app_version),
            P.CONTEXT = e.context,
            e.page && (e.page.title || _.keys(e.page.meta).length) && P.pubsub.publish(P.CONST.PUBSUB_CHANNEL_SITE, P.CONST.PUBSUB_TOPIC_PAGE_INFO, e.page);
        },
        onResponseError: function(t, n)
        {
            var i = {
                type: "sentry",
                http_status: t.http_status,
                error_message: t.message,
                error_target: t.target
            };
            n && (i.api_code = n.api_error_code),
            e.error("Request error for " + this.name, i),
            this.trigger("error", t);
        },
        isEqual: function(e)
        {
            if (this.name !== e.name)
            {
                return !1;
            }
            var t = _.omit(this.options, "bookmarks"),
                n = _.omit(e.options, "bookmarks");
            return _.isEqual(t, n);
        },
        toString: function()
        {
            var e = _.omit(this.options, "bookmarks", "field_set_key");
            return this.name + "(" + P.toArgumentString(e) + ")";
        },
        isCalling: function()
        {
            return !!this.xhr;
        }
    }),
    P.stopwatch.wrapMethods(P.Resource.prototype, "Resource", ["call"]),
    P.Resource.NOOP_RESOURCE = {
        name: "NoopResource",
        options: {}
    };
}(),
function()
{
    P.ModalManager = function(e)
    {
        _.bindAll(this, "_onModalDestroyed", "_onKeyup"),
        this.$container = e || $("body"),
        this.modals = [];
    },
    _.extend(P.ModalManager.prototype, {
        showModal: function(e, t)
        {
            return this.modals.push(e),
            this.$container.append(e.getElement()),
            e.moduleOpener = t,
            e._setInDom(!0),
            e.on(P.CONST.EVENT_DESTROYED, this._onModalDestroyed),
            e.show(),
            1 === this.modals.length && this._addListeners(),
            e;
        },
        removeModal: function(e)
        {
            e.destroy();
        },
        removeAllModals: function(e)
        {
            _.each(this.modals,
                function(t)
                {
                    (e || t.getCanDismiss()) && t.destroy();
                });
        },
        showInModal: function(e, t, n)
        {
            var i = {
                module: e
            };
            _.extend(i, t);
            var o = this,
                s = {
                    name: "Modal",
                    options: i
                };
            P.loadModule(s,
                function(e)
                {
                    o.showModal(e, n);
                });
        },
        _onModalDestroyed: function(e)
        {
            var t = e.target;
            t.off(P.CONST.EVENT_DESTROYED, this._onModalDestroyed),
            this.modals = _.filter(this.modals,
                function(e)
                {
                    return t !== e;
                }),
            this.modals.length || this._removeListeners();
        },
        _addListeners: function()
        {
            $(document).on("keyup", this._onKeyup);
        },
        _removeListeners: function()
        {
            $(document).off("keyup", this._onKeyup);
        },
        _onKeyup: function(e)
        {
            e.keyCode === P.keyCode.ESCAPE && this.removeAllModals(!1);
        }
    });
    var e = null;
    P.stopwatch.wrapMethods(P.ModalManager.prototype, "ModalManager", ["showModal", "showInModal"]),
    P.ModalManager.instance = function()
    {
        return e || (e = new P.ModalManager),
        e;
    };
}(),
function()
{
    "use strict";
    function e(e, t, i, o)
    {
        var s = $.Deferred(),
            r = [],
            a = e.$el,
            l = _.map(t, i);
        return $.when.apply($, l).then(function()
        {
            _.each(arguments,
                function(e)
                {
                    r = r.concat(e.errors);
                });
            var t = {
                $el: a,
                errors: r
            };
            e.trigger(n, t),
            o && o(t),
            s.resolve(t);
        }),
        s.promise();
    }
    var t = "hasError",
        n = "validated",
        i = "disabled",
        o = "[type=submit]",
        s = 100,
        r = ["pinterest", "password", "123456", "welcome", "ninja", "abc123", "123456789", "12345678", "sunshine", "princess", "qwerty", "master", "michael", "jordan", "dragon", "soccer", "killer", "pepper", "devil", "princess", "1234567", "iloveyou"],
        a = function(e, t)
        {
            this.$el = e,
            this.rules = t;
        };
    _.extend(a.prototype, Backbone.Events, {
        validate: function(t)
        {
            var n = this;
            return e(this, this.rules,
                function(e)
                {
                    return e(n.$el);
                },
                t);
        }
    }),
    a.Required = function(e)
    {
        return function(t, n)
        {
            var i = $.Deferred(),
                o = t.val(),
                s = [],
                r = "checkbox" === t.attr("type") && !t.is(":checked"),
                a = "radio" === t.attr("type") && !t.is(":checked");
            if (r || a || !o)
            {
                var l = e && e.message ? e.message : P.string("formFieldRequired");
                s.push(l);
            }
            var u = {
                $el: t,
                errors: s
            };
            return n && n(u),
            i.resolve(u),
            i.promise();
        };
    },
    a.Email = function(e)
    {
        return function(t, n)
        {
            var i = $.Deferred(),
                o = $.trim(t.val()),
                s = [];
            if (o && !o.match(/.+@.+\..+/gi))
            {
                var r = e && e.message ? e.message : P.string("formEmailNotValid");
                s.push(r);
            }
            var a = {
                $el: t,
                errors: s
            };
            return n && n(a),
            i.resolve(a),
            i.promise();
        };
    },
    a.URL = function(e)
    {
        return function(t, n)
        {
            var i = $.Deferred(),
                o = t.val(),
                s = [];
            if (o && !o.match(/^(https?:\/\/){0,1}[a-z0-9_\-]+\..+/gi))
            {
                var r = e && e.message ? e.message : P.string("formURLNotValid");
                s.push(r);
            }
            var a = {
                $el: t,
                errors: s
            };
            return n && n(a),
            i.resolve(a),
            i.promise();
        };
    },
    a.Password = function(e)
    {
        return function(t, n)
        {
            var i = $.Deferred(),
                o = t.val(),
                s = [],
                a = {
                    shortPassStr: e && e.shortPassStr ? e.shortPassStr : P.string("passwordTooShort"),
                    badPassStyle: e && e.badPassStyle ? e.badPassStyle : P.string("passwordBadStyle"),
                    samePasswordStr: e && e.samePasswordStr ? e.samePasswordStr : P.string("passwordSamePasswordStr"),
                    blackPassStr: e && e.blackPassStr ? e.blackPassStr : P.string("passwordBlackPasswordStr"),
                    goodPassStr: e && e.goodPassStr ? e.goodPassStr : P.string("passwordGoodPasswordStr"),
                    userid: $('[name="username"]').length ? $('[name="username"]').val() : ""
                },
                l = $.fn.teststrength(o, a, r);
            if (l.length)
            {
                var u = l[l.length - 1];
                if (u)
                {
                    var c = l[0];
                    s.push(c);
                }
            }
            var d = {
                $el: t,
                errors: s
            };
            return n && n(d),
            i.resolve(d),
            i.promise();
        };
    },
    a.Length = function(e)
    {
        return function(t, n)
        {
            var i, o, s = $.Deferred(),
                r = t.val(),
                a = e.max || 1 / 0,
                l = e.min || 0,
                u = [],
                c = r.length;
            c < l ? (i = "Please enter at least " + l + " characters.", o = e && e.messages && e.messages.min ? e.messages.min : i, u.push(o)) : c > a && (i = "Please enter no more than " + a + " characters.", o = e && e.messages && e.messages.max ? e.messages.max : i, u.push(o));
            var d = {
                $el: t,
                errors: u
            };
            return n && n(d),
            s.resolve(d),
            s.promise();
        };
    },
    P.Validator = a,
    P.Form = function(e, t, i)
    {
        var o = this;
        i = i || {},
        this.$el = e,
        this.validators = {},
        this.errorFields = {},
        this.fastValidateFields = {},
        this.prevalidating = !!i.prevalidate,
        _.bindAll(this, "onFieldBlur", "onFieldChange", "onFieldKeyup", "onFieldValidated"),
        _.each(t,
            function(e, t)
            {
                var i = o.getField(t);
                if (i[0])
                {
                    var s = new P.Validator(i, e);
                    o.validators[t] = s,
                    s.on(n, o.onFieldValidated),
                    i.on("blur", o.onFieldBlur),
                    i.on("change", o.onFieldChange),
                    i.on("keyup", o.onFieldKeyup);
                }
                else
                {
                    P.log("WARN", t + " wasn't found in the form");
                }
            }),
        this.prevalidating && this.validate(function()
        {
            o.prevalidating = !1;
        }),
        e.submit(function()
        {
            return o.trigger("submitStarted", e),
            o.validate(function(e, t)
            {
                o.trigger(P.CONST.EVENT_SUBMIT_VALIDATED, e, t);
            }),
            !1;
        }),
        e.find("[placeholder]").placeholder();
    },
    _.extend(P.Form.prototype, Backbone.Events, {
        validate: function(t)
        {
            return e(this, this.validators,
                function(e)
                {
                    return e.validate();
                },
                t);
        },
        getField: function(e)
        {
            return this.$el.find("[name=" + e + "]");
        },
        getFieldErrorMessages: function(e)
        {
            return e.nextAll(".formErrorMessage");
        },
        getFieldLabels: function(e)
        {
            var t = e.attr("id"),
                n = this.$el.find('label[for="' + t + '"]'),
                i = e.closest("label", this.$el);
            return n.add(i);
        },
        validateField: function(e, t)
        {
            var n = e.attr("name");
            return this.validators[n].validate(t);
        },
        getValue: function(e)
        {
            var t = this.getField(e);
            return "checkbox" === t.attr("type") ? "checked" === t.attr("checked") : t.val();
        },
        getSubmitButtons: function()
        {
            return this.$el.find(o);
        },
        disableSubmitButtons: function()
        {
            this.getSubmitButtons().prop(i, !0);
        },
        enableSubmitButtons: function()
        {
            this.getSubmitButtons().prop(i, !1);
        },
        hasErrors: function()
        {
            return _.find(this.errorFields,
                function(e)
                {
                    return e;
                }) || !!this.$el.find("." + t)[0];
        },
        setFieldErrors: function(e, n)
        {
            this.clearFieldErrorMessages(e);
            var i = !!n[0];
            if (this.errorFields[e.attr("name")] = i, !this.prevalidating)
            {
                var o = this.getFieldLabels(e),
                    s = o.add(e);
                s.toggleClass(t, i),
                this.appendFieldErrorMessages(e, n);
            }
        },
        appendFieldErrorMessages: function(e, t)
        {
            t && t.length && e.parent().children().last().after('<p class="formErrorMessage">' + t.join(" ") + "</p>");
        },
        clearFieldErrorMessages: function(e)
        {
            var t = this.getFieldErrorMessages(e);
            t.remove();
        },
        enableFastValidateOnField: function(e)
        {
            this.fastValidateFields[e] = 1;
        },
        onFieldValidated: function(e)
        {
            var t = e.$el,
                n = e.errors;
            n[0] && this.enableFastValidateOnField(t.attr("name")),
            this.setFieldErrors(t, n),
            this.hasErrors() ? this.disableSubmitButtons() : this.enableSubmitButtons();
        },
        onFieldKeyup: function(e)
        {
            if (e.keyCode !== P.keyCode.TAB)
            {
                var t = $(e.target);
                this.fastValidateFields[t.attr("name")] && this.validateField(t);
            }
        },
        onFieldBlur: function(e)
        {
            var t = this,
                n = $(e.target);
            _.delay(function()
            {
                t.validateField(n);
            },
                s);
        },
        onFieldChange: function(e)
        {
            var t = $(e.target);
            this.validateField(t);
        }
    });
}(),
function()
{
    P.BrowserHistory = function(e)
    {
        this._onRemoved = e,
        this._uidToData = {},
        this._views = [],
        this._currentIndex = -1;
    },
    _.extend(P.BrowserHistory.prototype, {
        add: function(e)
        {
            var t = this.getCurrentUid(),
                n = void 0 === this._uidToData[t],
                i = n && null !== t;
            t = null !== t ? t : this._getNewUid(),
            n ? (i || (this._removeViewsAfter(this._currentIndex), this._saveState(t)), this._insert(t)) : this._currentIndex = this._views.indexOf(t),
            this._uidToData[t] = e;
        },
        _insert: function(e)
        {
            var t = this._views.length;
            if (0 === t || e > this._views[t - 1])
            {
                return this._views.push(e),
                this._currentIndex = t,
                void 0;
            }
            for (var n = 0; n < t; n++)
            {
                var i = this._views[n];
                if (e < i)
                {
                    this._views.splice(n, 0, e),
                    this._currentIndex = n;
                    break;
                }
                if (e === i)
                {
                    this._currentIndex = n,
                    P.log("ERROR", "Duplicate uid in browser history.");
                    break;
                }
            }
        },
        _removeViewsAfter: function(e)
        {
            e < 0 && (e = -1);
            var t = this,
                n = this._views.slice(e + 1);
            _.each(n,
                function(e)
                {
                    var n = t._uidToData[e];
                    t._onRemoved && t._onRemoved(n),
                    delete t._uidToData[e];
                }),
            this._views = this._views.slice(0, e + 1);
        },
        _saveState: function(e)
        {
            window.history.replaceState({
                    uid: e
                },
                document.title, window.location.href);
        },
        getCurrentUid: function()
        {
            var e = window.history.state && void 0 !== window.history.state.uid ? window.history.state.uid : null;
            return e;
        },
        _getNewUid: function()
        {
            return window.history.length;
        },
        getCurrent: function()
        {
            return this._uidToData[this.getCurrentUid()];
        },
        get: function(e)
        {
            return this._uidToData[e];
        }
    });
}(),
function()
{
    P.SimpleBrowserHistory = function()
    {
        this._uidToData = {};
    },
    _.extend(P.SimpleBrowserHistory.prototype, {
        add: function(e)
        {
            var t = this.getCurrentUid();
            t = null !== t ? t : this._getNewUid(),
            this._uidToData[t] = e;
        },
        getCurrentUid: function()
        {
            return window.location.href;
        },
        _getNewUid: function()
        {
            return window.location.href;
        },
        getCurrent: function()
        {
            return this._uidToData[this.getCurrentUid()];
        },
        get: function(e)
        {
            return this._uidToData[e];
        }
    });
}(),
function()
{
    var e = 10,
        t = function(e, t)
        {
            this.uid = e,
            this.item = t,
            this.next = null,
            this.prev = null;
        };
    P.LruCache = function(t)
    {
        this._maxNumItems = t || e,
        this._uidToData = {},
        this._numItems = 0,
        this._firstData = null,
        this._lastData = null;
    },
    _.extend(P.LruCache.prototype, {
        set: function(e, n)
        {
            var i = this._uidToData[e];
            i || (i = new t(e, n), this._uidToData[e] = i, this._numItems += 1),
            this._moveToFront(i),
            this._numItems > this._maxNumItems && this._evict();
        },
        get: function(e)
        {
            var t = this._uidToData[e];
            return t ? (this._moveToFront(t), t.item) : null;
        },
        remove: function(e)
        {
            var t = this._uidToData[e];
            t && (delete this._uidToData[e], this._firstData === t && (this._firstData = t.next), this._lastData === t && (this._lastData = t.prev), t.prev && (t.prev.next = t.next), t.next && (t.next.prev = t.prev), this._numItems -= 1);
        },
        _moveToFront: function(e)
        {
            this._firstData !== e && (this._firstData ? (this._lastData === e && (this._lastData = e.prev), e.prev && (e.prev.next = e.next), e.next && (e.next.prev = e.prev), this._firstData.prev = e, e.next = this._firstData, e.prev = null, this._firstData = e) : (this._firstData = e, this._lastData = e));
        },
        _evict: function()
        {
            delete this._uidToData[this._lastData.uid],
            this._firstData === this._lastData ? (this._firstData = null, this._lastData = null) : (this._lastData = this._lastData.prev, this._lastData.next = null),
            this._numItems -= 1;
        }
    });
}(),
function()
{
    var e = 10,
        t = function(e, t, n)
        {
            this.url = e,
            this.moduleUid = t,
            this.backgroundModuleUid = n || null,
            this.numHopsToBackground = 0;
        },
        n = function(e, t)
        {
            this.module = e,
            this.backgroundModule = t || null;
        },
        i = function()
        {
            this._browserHistory = null,
            this._seenModules = null,
            this._pageInfoCache = {},
            this._init();
        };
    _.extend(i.prototype, {
        start: function(e)
        {
            this._init(),
            e && (e.uid = this._getNewUid(e), this._addToHistory(e, null));
        },
        _init: function()
        {
            this._seenModules = new P.LruCache(e),
            this._browserHistory = new P.SimpleBrowserHistory;
        },
        navigate: function(e, t)
        {
            t.fromHistoryUid = this._browserHistory.getCurrentUid(),
            t.reuseLast = !!t.handled,
            P.navigate(e, t, {});
        },
        getModule: function(e, t)
        {
            var i = null,
                o = null,
                s = null,
                r = null;
            return r = t.reuseLast ? this._browserHistory.get(t.fromHistoryUid) : this._browserHistory.getCurrent(),
            r && (i = this._seenModules.get(r.moduleUid), s = r.moduleUid, o = this._seenModules.get(r.backgroundModuleUid)),
            i || (i = new e({}), s = null !== s ? s : this._getNewUid(i), i.uid = s),
            this._addToHistory(i, o),
            new n(i, o);
        },
        updateBackgroundModule: function(e, t)
        {
            var n = this._browserHistory.getCurrent(),
                i = this._browserHistory.get(t.fromHistoryUid);
            e ? (n.backgroundModuleUid = e.uid, this._seenModules.set(e.uid, e), t.fromNavigate && i && (n.numHopsToBackground = i.numHopsToBackground + 1)) : (n.backgroundModuleUid = null, n.numHopsToBackground = 0);
        },
        cancelNavigation: function()
        {
            var e = this._browserHistory.getCurrent();
            this._seenModules.remove(e.moduleUid),
            this._go(-1);
        },
        closeCurrentModule: function()
        {
            var e = this._browserHistory.getCurrent();
            e && 0 !== e.numHopsToBackground && this._go(-e.numHopsToBackground);
        },
        setPageInfo: function(e)
        {
            var t = this._getUrl();
            this._pageInfoCache[t] = e;
        },
        getPageInfo: function(e)
        {
            return e = e || this._getUrl(),
            this._pageInfoCache[e];
        },
        _go: function(e)
        {
            window.history.go(e);
        },
        _getUrl: function()
        {
            return window.location.href;
        },
        _getNewUid: function(e)
        {
            return e.cid;
        },
        _addToHistory: function(e, n)
        {
            var i = this._getUrl(),
                o = n ? n.uid : null,
                s = this._browserHistory.getCurrent();
            s || (s = new t(i, e.uid, o)),
            this._browserHistory.add(s),
            this._seenModules.set(e.uid, e),
            n && this._seenModules.set(o, n);
        }
    }),
    P.stopwatch.wrapMethods(i.prototype, "PushStateHistoryManager", ["closeCurrentModule"]);
    var o = function()
    {
        this._pageInfoCache = {};
    };
    _.extend(o.prototype, {
        start: P.NOOP,
        navigate: function(e, t)
        {
            P.navigate(e, t, {});
        },
        getModule: function(e)
        {
            return [new e({}), []];
        },
        updateBackgroundModule: P.NOOP,
        cancelNavigation: P.NOOP,
        closeCurrentModule: P.NOOP,
        setPageInfo: function(e)
        {
            var t = this._getUrl();
            this._pageInfoCache[t] = e;
        },
        getPageInfo: function(e)
        {
            return e = e || this._getUrl(),
            this._pageInfoCache[e];
        },
        _getUrl: function()
        {
            return window.location.href;
        }
    }),
    P.HistoryManager = P.useHistory() ? i : o,
    window.P_TEST_MODE && (P.PushStateHistoryManager = i, P.NoPushStateHistoryManager = o, P.HistoryRecord = t);
}(),
function()
{
    var e = "placeholder",
        t = "placeholder",
        n = "placeholder-visible",
        i = e in document.createElement("input");
    if (i)
    {
        return jQuery.fn.placeholder = function()
        {
            return this;
        },
        void 0;
    }
    var o = {
        initPlaceholder: function()
        {
            "password" !== this.attr("type") && (this.blur(o._onPlaceholderBlur), this.focus(o._onPlaceholderFocus), this.blur());
        },
        _onPlaceholderBlur: function()
        {
            o._setPlaceholder(this);
        },
        _setPlaceholder: function(i)
        {
            var o = $(i),
                s = o.val();
            s.length || (i[n] = !0, o.addClass(t), i.value = o.attr(e));
        },
        _onPlaceholderFocus: function()
        {
            o._clearPlaceholder(this);
        },
        _clearPlaceholder: function(e)
        {
            var i = $(e);
            e[n] && (e[n] = !1, i.removeClass(t), e.value = "");
        }
    };
    jQuery.fn.placeholder = function()
    {
        return o.initPlaceholder.apply(this),
        this;
    };
    var s = {
        get: function(t)
        {
            var i = $(t),
                o = t[n];
            return o && i.attr(e) === t.value ? "" : t.value;
        },
        set: function(e, t)
        {
            var i = $(e);
            return t && e[n] ? o._clearPlaceholder(e) : t || o._setPlaceholder(e),
            e.value = t,
            o._setPlaceholder(e),
            i;
        }
    };
    P.log("Adding hooks on input and textarea for placeholders."),
    $.valHooks.input = s,
    $.valHooks.textarea = s,
    $(document).delegate("form", "submit",
        function()
        {
            var e = $("input", this).each(o._clearPlaceholder);
            window.setTimeout(function()
            {
                e.each(o._setPlaceholder);
            },
                10);
        });
}(),
function()
{
    P.Positioning = {
        positionElementAtAnchor: function(e, t, n, i, o)
        {
            var s = P.CONST.PositionPointFlag,
                r = t.offset();
            e.offset();
            var a = e.outerWidth(),
                l = t.outerWidth(),
                u = 0,
                c = 0;
            if (n & s.FLAG_VERTICAL_BOTTOM || n & s.FLAG_VERTICAL_TOP ? (u = n & s.FLAG_VERTICAL_BOTTOM ? r.top + t.outerHeight() : r.top - e.outerHeight(), c = n & s.FLAG_VERTICAL_LEFT ? r.left : n & s.FLAG_VERTICAL_RIGHT ? r.left + l - a : r.left + (l - a) / 2) : (n & s.FLAG_HORIZONTAL_LEFT || n & s.FLAG_HORIZONTAL_RIGHT) && (c = n & s.FLAG_HORIZONTAL_LEFT ? r.left - a : r.left + l, u = n & s.FLAG_HORIZONTAL_TOP ? r.top : n & s.FLAG_HORIZONTAL_BOTTOM ? r.top + t.outerHeight() - e.outerHeight() : r.top + (t.outerHeight() - e.outerHeight()) / 2), i)
            {
                var d = u - $(window).scrollTop();
                d > 0 && (u = d);
            }
            var h = {
                left: c,
                top: u
            };
            return o && (h = this.checkIfInViewportAndAdjustAccordingly(e, h, n)),
            e.css(h),
            n;
        },
        checkIfInViewportAndAdjustAccordingly: function(e, t)
        {
            e.offset();
            var n, i, o = e.width(),
                s = t.left,
                r = t.top,
                a = s + o,
                l = 7;
            a > P.Viewport.width ? n = s - (a - P.Viewport.width + l) : s < 0 && (n = l);
            var u = {};
            return u.left = n ? n : s,
            u.top = i ? i : r,
            u;
        }
    };
}(),
function()
{
    P.TransitionState = {
        NOT_STARTED: 0,
        STARTED: 1,
        ENDED: 2
    };
    var e = function(e)
    {
        return {
            "animation-duration": e,
            "-webkit-animation-duration": e,
            "-o-animation-duration": e
        };
    },
        t = function(e)
        {
            return {
                width: e.width + "px",
                height: e.height + "px"
            };
        },
        n = function(e)
        {
            return {
                top: e.top + "px",
                left: e.left + "px"
            };
        },
        i = function(e)
        {
            return {
                transition: e,
                "-moz-transition": e,
                "-webkit-transition": e,
                "-o-transition-duration": e
            };
        };
    P.Transition = function(e, t, n, i)
    {
        this.element = e,
        this.endPos = t,
        this.endDim = n,
        this.duration = i,
        this.state = P.TransitionState.NOT_STARTED,
        this.listener = null;
    },
    _.extend(P.Transition.prototype, {
        start: function()
        {
            this.state = P.TransitionState.STARTED,
            this.onStart(),
            this.listener.started();
            var e = this;
            setTimeout(function()
            {
                e.end();
            },
                this.duration);
        },
        end: function()
        {
            this.state = P.TransitionState.ENDED,
            this.onEnd(),
            this.listener.ended();
        },
        addListener: function(e)
        {
            this.listener = e;
        },
        onStart: function()
        {
        },
        onEnd: function()
        {
        }
    }),
    P.Transition.extend = Backbone.View.extend,
    P.Transition.Zoom = P.Transition.extend({
        onStart: function()
        {
            var e = this.duration / 1e3,
                o = "all " + e + "s ease-out",
                s = _.extend({
                        position: "fixed"
                    },
                    i(o), t(this.endDim), n(this.endPos));
            this.element.css(s);
        }
    }),
    P.Transition.Spin = P.Transition.extend({
        onStart: function()
        {
            var o = this.duration / 1e3 + "s",
                s = "all " + o + " ease-out",
                r = _.extend({
                        position: "fixed"
                    },
                    i(s), e(o), t(this.endDim), n(this.endPos));
            this.element.addClass("rotate").css(r);
        }
    });
}(),
function()
{
    var e = null,
        t = function()
        {
        };
    _.extend(t.prototype, Backbone.Events, {
        connect: function(e, t)
        {
            t = _.extend({},
                {
                    success: P.NOOP,
                    error: P.NOOP,
                    complete: P.NOOP
                },
                t);
            var n, i = P.FacebookDialog._getWindowOptions();
            if (n = window.open("/connect/" + e + "/", null, i), !n)
            {
                return P.showError(P.string("popupErrorMessage")),
                void 0;
            }
            var o = this,
                s = setInterval(function()
                {
                    n.closed && (clearInterval(s), o.handleComplete({
                        network: e,
                        error_message: "Window closed."
                    }));
                },
                    1e3);
            this.once("connect:" + e,
                function(e)
                {
                    clearInterval(s),
                    e.error_message ? t.error(e) : t.success(e),
                    t.complete();
                });
        },
        complete: function(e)
        {
            var t = JSON.parse(e);
            this.handleComplete(t);
        },
        handleComplete: function(e)
        {
            var t = "connect:" + e.network;
            this.trigger(t, e);
        }
    }),
    _.extend(t, {
        instance: function()
        {
            return e || (e = new t),
            e;
        },
        FACEBOOK: "facebook",
        TWITTER: "twitter",
        GOOGLE: "google",
        YAHOO: "yahoo"
    }),
    P.SocialConnect = t;
}(),
function()
{
    P.FacebookDialog = {
        open: function(e)
        {
            var t = this._getWindowUrl(e),
                n = this._getWindowOptions();
            return window.open(t, null, n);
        },
        _getWindowUrl: function(e)
        {
            var t = ["description", "name", "picture"],
                n = _.extend({
                        app_id: P.FB_KEY,
                        display: "popup"
                    },
                    _.pick(e, t));
            n.link = P.absolutify(e.path),
            n.redirect_uri = P.absolutify("/close_window/");
            var i = _.contains(["send", "feed"], e.type),
                o = i ? e.type : "feed",
                s = "https://www.facebook.com/dialog/" + o + "?",
                r = $.param(n);
            return s + r;
        },
        _getWindowOptions: function()
        {
            var e = 580,
                t = 400,
                n = screen.width,
                i = screen.height,
                o = Math.round((n - e) / 2),
                s = i > t ? Math.round((i - t) / 2) : 0;
            return "scrollbars=yes,resizable=yes,toolbar=no,location=yes,width=" + e + ",height=" + t + "," + "left=" + o + ",top=" + s;
        }
    };
}(),
function()
{
    var e = "offsite_",
        t = "-";
    P.SafeLink = {
        open: function(n, i)
        {
            var o = Math.round(1e3 * Math.random()) + "",
                s = Math.round(1e3 * Math.random()) + "";
            Cookie.set(e + o, s);
            var r = {
                token: o + t + s,
                url: n
            };
            i && (r.pin = i),
            P.changeWindowLocation("/offsite/?" + $.param(r), !0);
        },
        validateToken: function(n)
        {
            if (!n)
            {
                return !1;
            }
            var i = n.split(t),
                o = i[0],
                s = i[1],
                r = e + o,
                a = Cookie.get(r, s);
            return Cookie.unset(r),
            a === s;
        },
        checkLink: function(e, t)
        {
            var n = {
                name: "ConfirmDialog",
                options: {
                    template: "offsite_warning"
                },
                resource: {
                    name: "OffsiteLinkResource",
                    options: {
                        url: e,
                        pin_id: t && t.pin_id
                    }
                }
            };
            P.loadModule(n,
                function(e)
                {
                    e.render(function()
                    {
                        var n = e.data,
                            i = t && t.proceed,
                            o = t && t.cancel;
                        n && "safe" === n.redirect_status ? i && i(n) : (P.ModalManager.instance().showInModal(e), e.on(P.CONST.EVENT_CONFIRM,
                                function()
                                {
                                    i && i(n),
                                    e.off(P.CONST.EVENT_DESTROYED, o);
                                }), e.on(P.CONST.EVENT_DESTROYED, o), e.on("navigate",
                                    function(e)
                                    {
                                        e.data.$el && e.data.$el.hasClass("safe") && (e.stopPropagation(), window.location.replace(e.data.url));
                                    }));
                    });
                });
        }
    };
}(),
function()
{
    P.Updater = function()
    {
        this.decay = 0,
        this.lastFetchTime = 0,
        this.timeout = null,
        this.recentPinId = null,
        this.updatesResource = new P.Resource("UpdatesResource", {});
        var e = this;
        $(document).on("mousemove", _.throttle(function()
        {
            e.wake();
        },
            1e3)),
        this.deferredFetch();
    },
    _.extend(P.Updater.prototype, Backbone.Events, {
        getUpdatesResourceOptions: function()
        {
            var e = {};
            return this.recentPinId && (e.last_pin_id = this.recentPinId),
            e;
        },
        setRecentPinId: function(e)
        {
            this.recentPinId = e;
        },
        wake: function()
        {
            this.msSinceLastFetch() > P.CONST.UPDATES_MIN_POLL && (this.decay = 0, this.fetch());
        },
        fetch: function()
        {
            var e = this;
            clearTimeout(this.timeout),
            this.lastFetchTime = (new Date).getTime(),
            this.updatesResource.setOptions(this.getUpdatesResourceOptions()),
            this.updatesResource.call("get", {
                success: function(t)
                {
                    var n = t.resource_response.data;
                    _.each(n,
                        function(t, n)
                        {
                            e.trigger(n, t);
                        }),
                    e.deferredFetch();
                },
                error: function()
                {
                    e.decay = 1e4,
                    e.deferredFetch();
                }
            });
        },
        deferredFetch: function()
        {
            this.decay = Math.min(2 * (this.decay || 1e3), P.CONST.UPDATES_MAX_POLL);
            var e = this;
            this.timeout = setTimeout(function()
            {
                e.fetch();
            },
                P.CONST.UPDATES_MIN_POLL + this.decay);
        },
        msSinceLastFetch: function()
        {
            return (new Date).getTime() - this.lastFetchTime;
        }
    }),
    P.Updater.instance = function()
    {
        return P.Updater._instance || (P.Updater._instance = new P.Updater),
        P.Updater._instance;
    };
}(),
function()
{
    var e = 5;
    P.TypeaheadProvider = function(t)
    {
        t = t || {},
        this.tags = t.tags,
        this.enable_recent_queries = !!t.enable_recent_queries,
        this.searchResource = new P.Resource("TypeaheadResource", {
            tags: t.tags,
            pin: t.pin_id,
            count: e
        }),
        this.itemsCache = new P.LruCache;
    },
    _.extend(P.TypeaheadProvider.prototype, Backbone.Events, {
        search: function(e, t)
        {
            var n;
            if (e = $.trim(e), !e && "sendPin" === this.tags)
            {
                return this.abortSearch(),
                this.publishData(e, [], t);
            }
            if (!e && this.enable_recent_queries && P.currentUser && P.currentUser.isAuthenticated())
            {
                n = "recent_search";
            }
            else
            {
                var i = this.itemsCache.get(e);
                if (i && i.length)
                {
                    return this.abortSearch(),
                    this.publishData(e, i, t),
                    void 0;
                }
            }
            this.fetch(e, n, t);
        },
        abortSearch: function()
        {
            this.searchResource.abort();
        },
        publishData: function(e, t, n)
        {
            var i = {
                term: e,
                items: t
            };
            this.trigger(P.CONST.EVENT_DATA, i),
            n && n(i);
        },
        setAutocompleteScope: function(e)
        {
            this.searchResource.set("autocompleteScope", e);
        },
        fetch: function(e, t, n)
        {
            var i = this.searchResource;
            if (i.isCalling())
            {
                var o = i.get("term");
                if (e === o)
                {
                    return;
                }
                this.abortSearch();
            }
            var s = this;
            this.searchResource.set("term", e),
            this.searchResource.set("tags", t || this.tags),
            this.searchResource.resetBookmark(),
            this.searchResource.call("get", {
                success: function(t)
                {
                    var i = t.resource_response.data;
                    s.cacheData(e, i),
                    s.publishData(e, i, n);
                },
                error: function(e)
                {
                    s.trigger("fetchError", e);
                }
            }),
            this.warm = !0;
        },
        cacheData: function(e, t)
        {
            this.itemsCache.set(e, t);
        },
        prefetch: function()
        {
            if (!this.warm)
            {
                var e = new P.Resource("TypeaheadPrepareResource");
                e.call("get", {
                    success: P.NOOP,
                    error: P.NOOP
                }),
                this.warm = !0;
            }
        }
    });
}(),
function()
{
    P.TemplateModuleLoader = function()
    {
        this._templateModules = {};
    },
    P.TemplateModuleLoader.prototype = {
        registerTemplateModule: function(e)
        {
            e.className && e.options.is_template_module && (this._templateModules[e.className] = {
                options: e.options,
                tree: e._moduleTree,
                html: e._html
            });
        },
        getTemplateModule: function(e)
        {
            return this._templateModules[e];
        },
        buildTemplateModule: function(e)
        {
            if (!e.moduleName)
            {
                return P.log("ERROR", "TemplateModules require a module name."),
                void 0;
            }
            var t = this,
                n = e.callback,
                i = e.data || {},
                o = this.getTemplateModule(e.moduleName),
                s = {
                    module: {
                        html: o.html,
                        tree: o.tree
                    }
                },
                r = {
                    name: e.moduleName,
                    options: o.options
                };
            P.loadModule(r,
                function(e)
                {
                    var o = P.NOOP;
                    n && (o = function()
                    {
                        var o = function()
                        {
                            n.call(t, e);
                        };
                        e.loadFromData(i, o);
                    }),
                    e.loadFromModuleTree(s.module.html, s.module.tree, !1, o);
                });
        }
    };
    var e = null;
    P.TemplateModuleLoader.instance = function()
    {
        return e || (e = new P.TemplateModuleLoader),
        e;
    };
}();